• 締切済み

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

  • Delphi のTComboBoxについて

    DelphiのTComboBoxについて質問があります。 SQLを走らせて検索結果をTComboBoxに格納しようと考えています。 例えばTComboBoxのNameをTCMBとしたとして -------------------------------- SQL発行 while 検索データEOF do begin TCMB.add(検索結果); 次のデータ見る(Fetch); end; -------------------------------- と上記のようになります。 しかし検索結果が同じデータがあった場合もTComboBoxに格納してしまいます。 TComboBoxには重複データを格納したくありません。 そこでいい方法というかTComboBoxの特徴(プロパティやらメソッドやら)あります でしょうか? ちなみにSQLはDISTINCTなどは使えず常に同じものを取得するようになっています。

  • 直線検出のハフ変換プログラム(delphi)

    ただいまdelphiで直線検出のハフ変換のプログラムを書いているのですが、コンパイルし、実行しようとするとスタックオーバーフローになってしまいます。 おそらく2次元配列のcounterの部分だと思うのですが、どなたか回避の仕方お分かりになるでしょうか? ご存じの方いらっしゃいましたら教えて下さい。 下記にハフ変換の部分のコードを載せます。 他にも何か気付いた点ありましたらご指摘お願いいたします。 ○直線検出のハフ変換○ var i, j, k, n: Integer; rx, ry: Integer; clr: tcolor; R: longint; counter_max: Integer; THETA_RESOLUTION, RHO_RESOLUTION, LNUMBER_MAX: Integer; pai: Double; theta, rho: Integer; theta_max, rho_max, count: Integer; theta_cut, rho_cut: Integer; counter:array[0..1023,0..1999] of Integer; //直線検出のためのカウンタ sn:array[0..1023] of Double; //sin cs:array[0..1023] of Double; //cos begin THETA_RESOLUTION:=1024; //thetaの範囲は0から1023まで RHO_RESOLUTION:=2000; //rhoの範囲は-1000から999まで LNUMBER_MAX:=15; //検索する電線の数は15まで pai:=PI / THETA_RESOLUTION; //π÷THETA_RESOLUTION for i:=0 to 1023 do //sinとcosのテーブルを用意 begin sn[i]:=Sin(pai*i); cs[i]:=Cos(pai*i); end; //ハフ変換の実行// for rx:=0 to 639 do begin for ry:=0 to 479 do begin clr:=image1.Canvas.Pixels[rx,ry]; R:=colortorgb(clr); if(getrvalue(R)=0)and(getgvalue(R)=0)and(getbvalue(R)=0) then //黒である for theta:=0 to 1023 do begin rho:=Trunc(rx*cs[theta]+ry*sn[theta]+0.5); counter[theta,rho+1000]:=counter[theta,rho+1000]+1; end; end; end; //ハフ逆変換の実行// for n:=0 to 14 do begin //counterが最大になるtheta_maxとrho_maxを求める// counter_max:=0; for theta:=0 to 1023 do begin for rho:=-RHO_RESOLUTION div 2 to RHO_RESOLUTION div 2-1 do begin if(counter[theta,rho+RHO_RESOLUTION div 2] > counter_max) then begin counter_max:=counter[theta,rho+RHO_RESOLUTION div 2]; theta_max:=theta; rho_max:=rho; count:=counter_max; end; end; end; //counter[theta_max,rho_max]の近傍を0にする// for i:=-20 to 20 do begin for j:=-10 to 10 do begin theta_cut:=theta_max+i; rho_cut:=rho_max+j; if(theta_cut < 0) then begin theta_cut:=theta_cut+THETA_RESOLUTION; rho_cut:=-rho_cut; end else if(theta_cut > THETA_RESOLUTION-1) then begin theta_cut:=theta_cut-THETA_RESOLUTION; rho_cut:=-rho_cut; end; counter[theta_cut,rho_cut+RHO_RESOLUTION div 2]:=0; //削除する end; end; //ハフ逆変換した結果の表示// if(theta_max<>0) then //垂線の線を描く begin for rx:=0 to 639 do begin ry:=Trunc((rho_max-rx*cs[theta_max])/sn[theta_max]+0.5); if(ry>=480)or(ry<0) then continue; image1.Canvas.Pixels[rx,ry]:=RGB(255,0,0); end; end; if(theta_max<>THETA_RESOLUTION div 2) then //水平の線を描く begin for ry:=0 to 479 do begin rx:=Trunc((rho_max-ry*sn[theta_max])/cs[theta_max]+0.5); if(rx>=640)or(rx<0) then continue; image1.Canvas.Pixels[rx,ry]:=RGB(255,0,0); end; end; //直線を形成するピクセルが60個未満になったら表示しない// if count<60 then break; end; end;

  • DelphiのプログラムをVB・C#・Javaにかきかえる時の記述

    学校の課題で、 わからないのでおしえてください。 program test; var i,sum:integer; begin sum:0; for i=1 to 100 do if i mod 2 =0 then sum:=sum+i end. というDelphiでのプログラムを、Visual Basic,C#,Java言語で 同じような動作をするように書くにはどのように書いたらいいのか教えてください。

  • Delphiでキー入力を投げたい

    ゲームコントローラに対応していないソフトウェアを、コントローラに対応させるべくプログラムを組んでいます。 Delphiのプログラムでコントローラからの入力を受け取り、該当するウインドウにメッセージを送信すればこの仕組みが実現できると考えたのです。 まず、以下の関数を記述しました。 function CallBackTest(WH: HWND; LP: LParam): BOOL stdcall; var Buff: array [0..255] of Char; begin if IsWindowVisible(WH) then if GetWindowText(WH, Buff, 255) <> 0 then TListBox(LP).Items.AddObject(Buff, Pointer(WH)); Result := True; end; 次に、ListBoxを用意して、以下を実行しました。 EnumWindows(@CallBackTest, Longint(ListBox1)); ListBoxには実行中のウインドウタイトルが表示されます。そこで、目的のウインドウ名を選択して for i := 0 to (ListBox1.Items.Count - 1) do if ListBox1.Selected[i] then PostMessage(hwnd(listbox1.Items[i]), WM_KEYDOWN, 入力キー名, 0); end; こんな感じで投げられるかな?と思ったのですが、悲しいほど無反応。 なにか根本的にやり方を間違えているのでしょうか・・・?

  • Delphi の文字列型stringについて

     以下のコードで string は AnsiString、Char は AnsiChar です。  buf: array[1..16] of Char; を  buf :string[16]; と宣言しては意図通りに動きません。なぜでしょう?  TPerson = record   Age : Integer;   Name: string[30];  end;  TPersonArray = array of TPerson; procedure TForm1.Nantoka; var  i,j: Integer;  buf: array[1..16] of Char; //buf :string[16]; ではダメ!  Fs : TFileStream;  R : TPersonArray; begin  SetLength(R, 100); //配列のサイズを決定  for i := 0 to 99 do //動的配列の添え字は常に0から始まる  begin   R[i].Age := Random(100);   for j := 1 to 16 do buf[j] := Chr( Random(26)+97 );   //buf :string[16]; では buf[j] が'文字'にならない!   R[i].Name := 'Stream '+buf;  end; end;

  • [Delphi] StrToInt64がしたい

    16バイトの文字列を8バイトのint64型に変換したいです 下記コードのようにやってみたのですが上手く動きません 何か間違っている、他に方法などがありましたら教えてください。 function HexToInt64(const S: string): Int64; const hexstr : string = '0123456789abcdefABCDEF'; var I,L,h,m: Integer; j: Int64; p: PByteArray; test: string; begin result:=-1; p := @j; L:=Length(s); test:= ''; if L <> 16 then Exit; for i:=1 to L do if Pos(s[i], hexstr)<=0 then Exit; h:= strtoint('$' + Copy(S,0,8)); CopyMemory(@p[0], @h, 8); m:= strtoint('$' + Copy(S,9,8)); CopyMemory(@p[8], @m, 8); CopyMemory(@j, @p, 16); result:=j; end;

  • Delphi6 ループ中にキー入力

    Delphi 6 です。 for next などのループの中で、stringgridのセルをEnterキーで選択させたい時、選択されるまで(キーが押されるまで)処理を進めたくない方法は、どうするんでしょうか? flg:=false; for i:=1 to 100 do begin ~諸々の処理で flg:=true; ~ if flg=true then x[i]:= stringgridの選択されたRow番号(はじめからフォーカスされている番号でなく) ~諸々の処理で flg:=false; ~ end;

  • Delphi for文

    これって、Delphiのバグですか?特性ですか? procedure TForm1.Button1Click(Sender: TObject); begin test(); end; //-------------------------- procedure TForm1.test(); var k,x:integer; begin paintbox1.Canvas.pen.Color:=clBlack ; x:=0; for k:=1 to 3 do begin paintbox1.Canvas.moveto(x,0); paintbox1.Canvas.lineto(x,paintbox1.Height); x:=x+2; end; end; forループ内にブレークポイントを付けて「k」の値の変化を見ると、3,2,1と逆順になります。 「x:=x+2」を「x:=x+k」に変更すると、1,2,3と普通の順になります。 なぜ、こうなるのか? 対処法はありますか? Delphi Ver6・ターボDelphi どちらも同じ状況です。

  • プログラムです。

     次のプログラムは何をするものでしょうか?ただし、自然数が入力されるそうです。   program test(input,output) var i,j,n:integer; begin read(n); s:=0; i:=1; j:=1; while i <=n do begin s:=s+j*i i:=i+1; j:=j*(-1) end writeln('n=' ,n:3,' のときs=',s:5) end 宜しくお願いします。

  • Pascalでの選択ソート

    program sort(input, output); const numofdata =100 ; var d: array [1..numofdata] of integer; i,j,k: integer; tmp: integer; begin for i:=1 to numofdata do begin read(d[i]); end; for i:=1 to numofdata-1 do begin j:=i; for k:=i+1 to numofdata do begin if d[j]>d[k] then j:=k; end; tmp:=d[j]; d[j]:=d[i]; d[i]:=tmp; end; for i:=1 to numofdata do begin writeln(d[i]) end end. このプログラムを、データ数(1個から最大10000個まで)を最初に入力できるように変更するには、どうすればよいのでしょうか。教えてください。