たびたび失礼します。
Delete文は無事通るようになったのですが、同じような処理でCommitしたときに
「トランザクションが有効でありません。」
となります。
データは保存されています。
IBTransaction.StartTransaction;
try
with IBQuery do
begin
SQL.Clear;
SQL.LoadFromFile(Select文);
Open;
if Locate('CODE',edtCode.Text,[])then begin
Close;
SQL.Clear;
SQL.LoadFromFile(UpDate文);
end else begin
Close;
SQL.Clear;
SQL.LoadFromFile(Insert文);
end;
//パラメータ入力
ParamByName('CODE').AsString := edtCode.Text;
ParamByName('…
ExecSQL;
end;
IBTransaction.Commit;//ここを通過するとエラー
except
IBTransaction.RollBack;
raise;
end;
なるべくトランザクションは手続き内で終了させてるはずなんですが。
↑追加&更新処理に関する質問です。
Insert文やUpDate文はIBDataSetのエディターを流用して作ったので問題ないはずです。
IBQueryのTransaction プロパティには、IBTransactionが設定されてますか?
されてます。
IBTransaction-IBDataBase-IBQueryの1セットを
をSQL文を書き換えて流用しています。
あと、
IBTransactionの DefaultDatabase プロパティには、IBDataBaseが指定されていますか?
また、
IBTransaction.StartTransaction;
のあと、
IBTransactionのInTransaction プロパティはtrueになってますか?
ご指摘ありがとうございます。
if IBTransaction.InTransaction then ShowMessage('OK');
をいろんな行に突っ込んでいったら、SQL文交換前のClose;で引っかかりました。
DataSetのClose;はトランザクション終わらせるんですか?
でも、トランザクションがスタートしたあとに同じようにSQL文を交換したDelete文は上手く通ってるんですよ。
> でも、トランザクションがスタートしたあとに同じように
> SQL文を交換したDelete文は上手く通ってるんですよ。
ソースを見た訳ではないので的外れかも知れませんが、Delete文の場合にはOpenしていないのではないでしょうか?私なら複数のTIBQueryを用いて以下のように書きます。
var
Flg: Boolean;
begin
IBTransaction.StartTransaction;
try
with IBQuery1 do
begin
SQL.LoadFromFile(Select文);
Open;
Flg := Locate('CODE',edtCode.Text,[]);
Close;
end;
with IBQuery2 do
begin
if Flg then
SQL.LoadFromFile(UpDate文);
else
SQL.LoadFromFile(Insert文);
//パラメータ入力
ParamByName('CODE').AsString := edtCode.Text;
ParamByName('…
ExecSQL;
end;
IBTransaction.Commit;
except
IBTransaction.RollBack;
raise;
end;
end;
# 本当はLocateを使わずにSQLのWhere句で処理したい所ですけどね。
誤: SQL.LoadFromFile(UpDate文);
正: SQL.LoadFromFile(UpDate文)
Delete文ではOpen→Close;はないです。
Locateを使わずにInsertとUpdateを切り分ける方法があるんですか?
すごく興味あります。
>Locateを使わずにInsertとUpdateを切り分ける方法があるんですか?
1.Where句でレコードがユニークになる条件を書いてレコードを特定。
2.Select文に"Select Count(*) From 〜"を指定して、Fields[0].AsIntegerを参照。
値が0ならば該当レコードなし、1ならば該当レコードあり。
2'.TIBQuery.IsEmptyを参照。
Trueならば該当レコードなし、Falseなら該当レコードあり。
レコードの存在を知るだけなら、上記いずれかが簡単です。
レコード数の多いDBではカレントの移動がない分だけ、高速に処理できます。
TIBQuery.RecordCountを調べる方法もありますが、Last/Firstをしないと
正常に件数が取得できない事が多く、カレントの移動が発生するので時間も掛かります。
# この辺は実際に試してみる事をオススメします。
IsEmptyを分岐に使ったんですが、やっぱり同じ結果です。
SQL文を交換する以上、IsEmptyにしろFieldsにしろOpenCloseが1回入りますよね。
やっぱりこの処理が問題なんですかね。
StartTransactionをSQL入れ替え直後に下げたら一応トランザクションが通りました。
当面これでごまかそうと思ってますが、競合対策も考えねばと思ってます。
Osamu'sSquareの記事を見たりしてたんですけど、トランザクションのパラメータでテーブルをロックするか、ロックもどきのフィールドを追加するしかなさそうなんですが、
編集中のレコードのみをロックするのは、どういう風なのがあるんでしょうか?
ツイート | ![]() |