• 締切済み

FirebirdへのDelphiによるデータ入力

Deldhi2010とFirebird2.5を使っています。 下記のコードでデータを入力しているのですが、実行中の他のプログラムで入力済みのデータが見えません。また、二つのPCで入力していくとTest_Noが二重に登録されます。入力したデータがデータベースに反映されていないように見えます。しかし、表示コードにもトランザクションを適応すると問題は解決しますが、理由がわかりません。ご指導よろしくお願いいたします。 (入力コード) procedure TForm.ButtonRegClick(Sender: TObject); var I:Integer; begin if not TIBTransaction.InTransaction then IBTransaction.StartTransaction; try with TIBQuery do begin Close; SQL.Clear; SQL.Add('select max(Test_No) from TESTDB'); Open; I:=FieldByName('max').AsInteger; // Close; SQL.Clear; SQL.Add('insert into TESTDB (Test_No,TempText) values (:TN,:TT)'); ParamByName('TN').AsInteger:=I+1; ParamByName('TT').AsString:='Test'; ExecSQL; end; IBTransaction.Commit; except IBTransaction.Rollback; ShowMessage('Reg Error !!'); end; (表示コード) with TStringGrid do begin RowCount:=1; Rows[0].Clear; end; with TIBQuery do begin Close; SQL.Clear; SQL.Add('select * from TESTDB order by Test_No'); Open; I:=0; First; while not Eof do begin inc(I); TStringGrid.RowCount:=I; TStringGrid.Cells[0,I-1]:=IntToStr(FieldByName('Test_No').AsInteger); TStringGrid.Cells[1,I-1]:=FieldByName('TempText').AsString; Next; end; end;

みんなの回答

回答No.2

最近Delphi触っていないので、間違ってたらごめんなさい。 トランザクションの排他レベル(トランザクションの分離レベル)の設定が不適切だと思われます。 > 実行中の他のプログラムで入力済みのデータが見えません。 他のプログラムでコミットする前に、そのデータを見たいなら、 →DirtyRead (しかし、InterBaseではDirtyReadは指定できないっぽい?) 他のプログラムでコミットしたデータを見たいなら、 →ReadCommitted 読み込み側が、暗黙のトランザクションで、RepeatableReadになっていませんか? > 二つのPCで入力していくとTest_Noが二重に登録されます。 MAX(Test_No)が3だとします。 1. プロセスAでMAX(Test_No)読み込み(A:3) 2. プロセスBでMAX(Test_No)読み込み(B:3) 3. プロセスAで+1を書き込み(A+1:4) 4. プロセスBで+1を書き込み(B+1:4) 5. プロセスAでコミット 6. プロセスBでコミット 2と3が入れ替わっても、トランザクションの排他レベルがDirtyReadでもなければ、 Test_No=4で登録されたレコードは見えないので一緒 SEQUENCEを使った方が良いのではないでしょうか?

murica
質問者

お礼

ご指摘の通り、TIBTransactionをReadCommittedに設定したらうまく動きました。 トランザクションのレベルの問題だと思いますが、10台ぐらいのPCで同じプログラムを使うぐらいでは、ReadCommittedで特に問題は起こらないですか? またTIBEventsとの関係は問題ないのでしょうか? 補足で書いたようにはならないのでしょうか? ご指導いただければ幸いです。 SEQUENCEは使ったことがないのですが、勉強してみます。 本当にありがとうございました。

murica
質問者

補足

ご指導ありがとうございます。 プロセスAとプロセスBが同時でなくてもTest_Noが二重に登録されます。 1. プロセスAでMAX(Test_No)読み込み(A:3) 3. プロセスAで+1を書き込み(A+1:4) 5. プロセスAでコミット 2. プロセスBでMAX(Test_No)読み込み(B:4) 4. プロセスBで+1を書き込み(B+1:5) 6. プロセスBでコミット とはならないのでしょうか?

noname#182251
noname#182251
回答No.1

直接の回答ではありません(^^;OKWaveはDelphiユーザーが少ないようです。 下記メーリングリストで質問しては如何でしょうか? http://www.freeml.com/delphi-users エキスパートが揃っていますし、レスポンスも早いことが多いです

murica
質問者

お礼

ありがとうございます。 早速質問してみたいと思います。

関連するQ&A