データベースを即時にコミットするには?

解決


めるめる  2007-04-06 05:35:10  No: 25654

いつもお世話になります。
データベース処理について知恵をお借りいたしたく、質問させていただきます。

下記環境にてデータを処理しています。
※実際には、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;


めるめる  2007-04-06 05:41:06  No: 25655

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;


りっきぃ  2007-04-09 21:44:07  No: 25656

ADOQueryにConnectionStringを設定しているということはそれぞれ別のコネクションを使用しているようですがそれには何か理由があるのでしょうか?
またそれぞれのクエリを実行したときのロックはどうしているのでしょうか?

問題となっている現象はボタン1で実行されるクエリが行もしくはテーブルロックをしているため、ボタン2を押下しても結果がすぐに反映されないからだと思われます。

対策としてはADOQuery1は表示だけというのであればLockTypeプロパティをltReadOnlyにすることで回避できると思います。

それでもダメというのであればADOConnectionを使用してロック戦術を一から見直す必要があります。


yyyyyyyy  2007-04-11 01:05:30  No: 25657

ADOQuery1,ADOQuery2 の Connection に
同じ ADOConnection オブジェクト を設定すれば逝けると思いますが。


めるめる  2007-04-11 20:36:30  No: 25658

りっきぃ様、yyyyyyyy様、ありがとうございます。

> ADOQueryにConnectionStringを設定しているということはそれぞれ別の
> コネクションを使用しているようですがそれには何か理由があるのでし
> ょうか?

(1)ADOQuery1は、WHERE句、ORDER BY句を指定した SELECT文専用として使用
※最初に条件を設定すると、ほとんど条件が変わることがない!
(2)ADOQuery2 は、INSERT文、DELETE文等、その他のSQL文用として使用

つまり、(1)で設定した条件文をいちいちセットしなおすのが面倒そうだっ
たので、同一のデータベースにもかかわらず、複数の ADOQueryを使用して
いたのが問題だったようです。
排他制御はデフォルトのまま、特に指定していないので、たぶんレコード
ロックだと思われます。

ADOQuery を一つだけにしたところ、問題は発生しなくなりました。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加