いつもお世話になります。
データベース処理について知恵をお借りいたしたく、質問させていただきます。
下記環境にてデータを処理しています。
※実際には、Button1, Button2 の処理を連続して実行しています。
本来は Button2 の処理が終了した時点で、空のデータが DBGrid1 に表示させたいのですが、
実際は Button3 の処理を何回か実行する、または、数秒してから実行するとやっと空のデータが表示されます。
しかもその時間も都度違いますし、たまに Button2 の処理が終了した時点で空データとなる場合もあります。
キャッシュの関係なのかバックグラウンド処理の影響なのかわかりませんが、Button2 の処理が終了した時点で
即時空のデータを表示させるには、何か良い方法はないでしょうか?
試しに、Sleep(5000) とか挿入してみましたが、これではあまりにも不細工です。
ADOQuery1.Refresh とかもダメでした。
解決策またはヒントがありましたらよろしくお願いいたします。
(WindowsVista + D7Pro)
ADOQuery1.Active := False;
ADOQuery1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\data.mdb;Persist Security Info=False';
DataSource1.DataSet := 'ADOQuery1';
DBGrid1.DataSource := 'DataSource1';
ADOQuery2.Active := False;
ADOQuery2.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\data.mdb;Persist Security Info=False';
※上記は実際はプログラムコードではなく、プロパティとして直接、値をセットしている
※ADOQuery1 と ADOQuery2 は同一のデータベースにコネクトしている
procedure TForm1.Button1Click(Sender: TObject);
var
Wstr: String;
begin
Wstr := 'SELECT * FROM TABLE WHERE NAME LIKE HOGE% ORDER BY NAME;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add(Wstr);
ADOQuery1.Open;
// DBGrid1 にデータが一覧表示される
end;
procedure TForm1.Button2Click(Sender: TObject);
var
Wstr: String;
begin
ADOQuery1.Close;
Wstr := 'DELETE FROM LC4';
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add(Wstr);
ADOQuery2.ExecSQL;
// ※ここに Sleep(5000); とか挿入する?
ADOQuery1.Open; // DBGrid1 に空っぽのデータが表示されるはず?
// しかし元のデータがそのまま表示されたまま!
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ADOQuery1.Close;
ADOQuery1.Open;
// 何回か、または数秒後に実行すると DBGrid1 に空のデータが表示される。
end;
procedure TForm1.Button2Click(Sender: TObject);
var
Wstr: String;
begin
ADOQuery1.Close;
Wstr := 'DELETE FROM TABLE'; // ← 書き間違いしてました!
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add(Wstr);
ADOQuery2.ExecSQL;
// ※ここに Sleep(5000); とか挿入する?
ADOQuery1.Open; // DBGrid1 に空っぽのデータが表示されるはず?
// しかし元のデータがそのまま表示されたまま!
end;
ADOQueryにConnectionStringを設定しているということはそれぞれ別のコネクションを使用しているようですがそれには何か理由があるのでしょうか?
またそれぞれのクエリを実行したときのロックはどうしているのでしょうか?
問題となっている現象はボタン1で実行されるクエリが行もしくはテーブルロックをしているため、ボタン2を押下しても結果がすぐに反映されないからだと思われます。
対策としてはADOQuery1は表示だけというのであればLockTypeプロパティをltReadOnlyにすることで回避できると思います。
それでもダメというのであればADOConnectionを使用してロック戦術を一から見直す必要があります。
ADOQuery1,ADOQuery2 の Connection に
同じ ADOConnection オブジェクト を設定すれば逝けると思いますが。
りっきぃ様、yyyyyyyy様、ありがとうございます。
> ADOQueryにConnectionStringを設定しているということはそれぞれ別の
> コネクションを使用しているようですがそれには何か理由があるのでし
> ょうか?
(1)ADOQuery1は、WHERE句、ORDER BY句を指定した SELECT文専用として使用
※最初に条件を設定すると、ほとんど条件が変わることがない!
(2)ADOQuery2 は、INSERT文、DELETE文等、その他のSQL文用として使用
つまり、(1)で設定した条件文をいちいちセットしなおすのが面倒そうだっ
たので、同一のデータベースにもかかわらず、複数の ADOQueryを使用して
いたのが問題だったようです。
排他制御はデフォルトのまま、特に指定していないので、たぶんレコード
ロックだと思われます。
ADOQuery を一つだけにしたところ、問題は発生しなくなりました。
ありがとうございました。
ツイート | ![]() |