[delphi-users:4847] FDQuery1.RecordCount値が50で頭打ちになる件

693 views
Skip to first unread message

OE

unread,
Feb 7, 2018, 4:38:31 AM2/7/18
to delphi...@freeml.com
こんにちは、OEです。
[環境]Delphi10 Seattle / Windows7

FireDACで SQLite にSelect文を行うと、
FDQuery1.RecordCount で得られる値が最大でも50で
頭打ちになってしまうのですね。
これを回避して正確なレコード数を得たいのですが、
今は while not FDQuery1.Eof do で回して数えています。

もし何かスマートな方法とか、根本的に解決する方法とか
ありましたら教えて頂けると助かります。

よろしくお願いいたします。

//-----------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
FDConnection1.Params.Clear;
FDConnection1.Params.Add('DriverID=SQLite');
//SQLite Sample Database
//http://www.sqlitetutorial.net/sqlite-sample-database/
FDConnection1.Params.Add('Database='
+ ExtractFilePath(Application.Exename)+'chinook.db');
FDPhysSQLiteDriverLink1.VendorLib :=
ExtractFilePath(Application.Exename)+'sqlite3.dll';
try
FDConnection1.Connected := True;
except
FDConnection1.Close;
Exit;
end;
FDQuery1.Connection := FDConnection1;

FDQuery1.Open('SELECT * FROM customers;');
ShowMessage(IntToStr(FDQuery1.RecordCount)); //50で頭打ち

while not FDQuery1.Eof do
begin
inc(i)
FDQuery1.Next;
end;
ShowMessage(IntToStr(i)); //正確なレコード数が表示される

FDQuery1.Close;
FDConnection1.Close;
end;


MLホームページ: https://www.freeml.com/delphi-users

----------------------------------------------------------------------
Powered by freeml -- https://www.freeml.com/ --
------------------------------------------------------[freeml byGMO]--

あなたの街のチラシがいつでも無料で見放題!
チラシをクリックしてチラシが拡大されたらポイントゲット♪
まずはかんたん登録♪ -ポイントタウン-
https://www.pointtown.com/ptu/rd.cgi?cid=8912
----------------------------------------------------------------------

赤推

unread,
Feb 7, 2018, 5:03:26 AM2/7/18
to delphi...@freeml.com
 赤推です。

一般的にRDBMSはOpenしただけではレコード数は分かりません。
したがって select count(*) from customers; で求めるのがオーソドックスな
やり方です。

FDQueryを1回余分にOpenするのが嫌なら、一旦FDQuery1.Lastで最終レコードま
で行けば、もしかしたら正しいRecordCountがセットされるのかもしれません。
以前TQueryの頃はOpenしたてはRecordCountに-1がセットされて、Last後は正し
い値が入るという仕様だったと記憶しています。

count(*)とLastでRDBMSやテーブルによってはスピードに差が出る場合がありま
す。

赤推

OE

unread,
Feb 7, 2018, 5:33:29 AM2/7/18
to delphi...@freeml.com
赤推 さん


> select count(*) from customers; で求めるのが
> オーソドックスなやり方

そうなのですね。
とっても素人な質問してしまいました。
恥ずかしい・・・。

> FDQuery1.Lastで最終レコード
> 正しいRecordCountがセットされるのかも

なるほど、こういう手法もあるのですね。
また試してみます。


大変助かりました、ありがとうございました。

OE

unread,
Feb 7, 2018, 7:24:45 PM2/7/18
to delphi...@freeml.com
おはようございます、OEです。
結果を書いていなかったので記録しておきます。
10,000レコードのサンプルを使って計測もしてみました。
なお「FDQuery1.Lastで最終レコードまで行く」方法については、
OpenしていないとLast実行時にエラーとなったので、Openさせました。

// 正しいレコード数は取得できない
FDQuery1.Open('SELECT CustomerId FROM customers;');
ShowMessage(IntToStr(FDQuery1.RecordCount));

// 正しいレコード数が取得でき、処理も速い
FDQuery1.Open('SELECT COUNT(*) FROM customers;');
ShowMessage(IntToStr(FDQuery1.Fields[0].Value));

// 正しいレコード数が取得できるが、比較して処理が遅い(1.5倍)
FDQuery1.Open('SELECT CustomerId FROM customers;');
FDQuery1.Last;
ShowMessage(IntToStr(FDQuery1.RecordCount));

ぽむぽむ

unread,
Feb 7, 2018, 8:56:59 PM2/7/18
to delphi...@freeml.com
解決していますが、
以下のように、RecordCountModeを全て(cmTotal)にすることで、正しい件数返してくれないでしょうか?

FDQuery1.FetchOptions.RecordCountMode := cmTotal;
FDQuery1.Open(''SELECT * FROM customers;'');
ShowMessage(IntToStr(FDQuery1.RecordCount));

内部処理的には、SELECT COUNT(*) FROM customers のようなSQLを
投げて、結果を返してくれるようですが。

(参考)FireDAC.Stan.Option.TFDFetchOptions.RecordCountMode
http://docwiki.embarcadero.com/Libraries/Berlin/ja/FireDAC.Stan.Option.TFDFetchOptions.RecordCountMode

たに

unread,
Feb 7, 2018, 8:58:26 PM2/7/18
to delphi...@freeml.com
おはようございます。
解決済みとなっていますが、一応補足させてもらいます。

FDQuery1.RecordCountが50となるのは、FDConnectionの初期値が関係しています。
FetchOptions.Mode = fmOnDemand かつ
FetchOptions.RowsetSize = 50 となっているため
初期レコードは50件のみ取得されます。
この状態で、全レコードデータを取得するには、
FDQuery1.FetchAll; を実行します。

また、はじめから全レコードデータを取得する場合は、
FetchOptions.Mode = fmAll を設定します。

但し、レコード数のみ取得したい場合は「SECELT COUNT(*)」が速いです。

よろしくです。

OE

unread,
Feb 8, 2018, 7:46:53 PM2/8/18
to delphi...@freeml.com
ぽむぽむ さん

RecordCountMode というオプションがあるのですね。
ありがとうございます。

しかし残念ながら、
> FDQuery1.FetchOptions.RecordCountMode := cmTotal;
を追記するとエラーが発生し、
> [FireDAC][Phys][SQLite] ERROR: near ";": syntax error.
となってしまいました。

RecordCountMode を使った例文を検索していますが見つけられ
なかったので良く分からぬままです。

しかし別の方法を提案して頂けて嬉しかったです。
ありがとうございました。

OE

unread,
Feb 9, 2018, 5:00:27 AM2/9/18
to delphi...@freeml.com
たに さん

なるほど、そういう部分が影響しているのですね。
またそれを回避する方法、そしてレコード数のみであれば
COUNT(*)が速いということ。
大変勉強になりました。

ありがとうございました。
Reply all
Reply to author
Forward
0 new messages