TUpdateSql ではまった...

Delphi 2005ではまった訳では無いのですが...

最近仕事で、データベースをUIと直接接続して更新画面を作成してます。
直接接続してるのは、そっちの方が楽かな?と思ったからですが、
編集した後、"やっぱやめ!"と言うことがやりたいためだけに、キャッシュアップデートを使用しています。RollBackを使う方法もあるのですが、何か負荷が大きそうなので使ってません。

で、更新対象がマスタ-ディテールタイプなのですが、マスタ側を削除したらディテール側も削除したいので、TUpdateSqlを二つ使って...とやり始めて、2つめのTUpdateSqlによる更新が何度やってもうまくいかない。
仕方なく、TUpdateSqlが入ってるDBTablesユニットを解読して、以下の問題箇所を発見。

procedure TUpdateSQL.ExecSQL(UpdateKind: TUpdateKind);
begin
with Query[UpdateKind] do
begin
Prepare;
ExecSQL;
if RowsAffected <> 1 then DatabaseError(SUpdateFailed);
end;
end;


でこの RowsAffected が比較している"1"ってどう意味だったっけ?とヘルプを引くと...

最新の問い合わせで実行対象だった行の数を返します。
(中略)
RowsAffectedプロパティを調べると,最新の問い合わせ処理で何行が更新または削除されたかがわかります。1行も更新または削除されなかった場合,RowsAffectedの値は0になります。エラーが原因でSQL文が実行されなかった場合は,RowsAffectedの値は-1になります。後者の場合は,通常,その前に例外が生成されます。

とある。ということは、ディテール側が0件だった場合にはRowsAffectedプロパティは0な訳で...
というか、キャッシュアップデートの更新は常に1件が対象?
まあ、1レコードの更新には1件のUpdateSqlが実行されるので、1件かもしれない。

 

仕方ないので、2個目のUpdateSqlを実行する際には、例外構文で例外クラスがEDatabaseErrorの時にはRowsAffectedが-1でない時以外はエラーを無視するようにしてしまいました。

この処理を見ていて思ったのは、キャッシュアップデートの範囲。TQueryなどDataSetがキャッシュしてたら別のQueryから更新をかけたらそ の更新はキャッシュされないのか?とか考えたが、TUpdateSqlの処理を見ていてうまくいくことから、データベースコンポーネントかセッションコン ポーネントあたりでキャッシュしてるようだ。

ということは、データベースコンポーネントかセッションコンポーネントを複数プログラムに追加したら、片方はキャッシュでもう片方は直でということが出来そうだ...

コメント (0件)


くろねこ研究所
https://www.blackcat.xyz/article.php/050525_tupdatesql