mysql:5273
From: kuroda <kuroda <kuroda@xxxxxxxxxx>>
Date: Wed, 27 Mar 2002 15:03:52 +0900
Subject: [mysql 05273] Delphi で LAST_INSERT_ID
はじめまして、黒田 といいます。 いつも勉強させていただき、ありがとうございます。 現在、Delphi にて MySQL にアクセスするプログラムを 書いているのですが、以下のような問題に遭遇し、解決 できずにおります。 [環境] サーバー側: RedHat6.2J MySQL3.23.46 (rpmでインストール) クライアント側: WinXP Home Delphi6 Update2 Delphi の dbExpress コンポーネント ・SQLConnection1 DBへの接続用 ・SQLQuery1 テーブルにINSERT(パラメータクエリ) ・SQLQuery2 LAST_INSERT_ID() を発行・取得 の3つのコンポーネントを使い、 1.ローカルにあるデータをサーバ上の MySQL に INSERT 2.その時の、AUTO_INCREMENT な項目の値を取得 という処理をするプログラムを書いたのですが、 LAST_INSERT_ID() が常に「0」を返してきてしまいます。 [うまくいかないコード] with SQLConnection1 do begin Open; end; with SQLQuery1 do begin ParamByName('fld_name').AsString:= 'kuroda'; ExecSQL; end; with SQLQuery2 do begin Open; id := Fields[0].AsInteger; // 常に「0」 end; 自分なりに調べたところ、 SQLConnection1 には、MaxStmtsPerConn という読み取り専用のプロパティ があり、実行時に確認したところ「1」でした。 この MaxStmtsPerConn というプロパティですが、Help によれば、 「現在の接続を使って実行できる文の数に対する制限がデータベースサーバーに よって設定されているかどうかを判別できます。MaxStmtsPerConn プロパティが 0 の場合,サーバーは制限を設定していません。1 つのデータベース接続を使 って,複数のデータセットをフェッチし,アクティブなデータセットが存在する 間,文を実行できます。MaxStmtsPerConn プロパティが 0 より大きい場合は, 実行できる文の数に対する制限がデータベースサーバーによって設定されていま す。サーバーは MaxStmtsPerConn プロパティで指定されている数だけのデータ セットを 1 つの接続で開くことができます。その数のデータセットが開かれる と,(たとえば Execute メソッドを使って)文をそれ以上実行することはでき ません。 デフォルトでは,MaxStmtsPerConn プロパティが 0 より大きい場合,サーバー で設定されている制限に達すると TSQLConnection はデータベース接続を複製し ます。たとえば,MaxStmtsPerConn プロパティが 1 の場合,同じ TSQLConnecti on コンポーネントを使って 2 つ目のデータセットを開こうとすると,TSQLConn ection は 2 つ目のデータセット用に 2 つ目のデータベース接続を確立します。」 案の定、サーバーに記録されたログをみたところ、 [うまくいかないときのログ] /usr/sbin/mysqld, Version: 3.23.46-log, started with: Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock Time Id Command Argument 020327 13:39:08 1 Connect kuroda@xxxxxxxxxx on db 020327 13:39:09 2 Connect kuroda@xxxxxxxxxx on db 2 Query INSERT INTO tbl ( fld_name) VALUES ('kuroda') 3 Connect kuroda@xxxxxxxxxx on db 3 Query SELECT LAST_INSERT_ID() 020327 13:39:10 1 Quit 3 Quit 2 Quit INSERT INTO 〜 と SELECT LAST_INSERT_ID() では、 別の接続(Id=2, 3)になってしまっています。 そこで、SQLQuery1 のみを使った以下のようなコードに変更したところ、 [うまくいくコード] with SQLConnection1 do begin Open; end; with SQLQuery1 do begin ParamByName('fld_name').AsString:= 'kuroda'; ExecSQL; Close; SQL.Text:='SELECT LAST_INSERT_ID()'; // SQL文を設定しなおす Open; id := Fields[0].AsInteger; // ちゃんと値が取得できる end; [うまくいったときのログ] 020327 13:44:30 4 Connect kuroda@xxxxxxxxxx on db 020327 13:44:31 5 Connect kuroda@xxxxxxxxxx on db 5 Query INSERT INTO tbl ( fld_name) VALUES ('kuroda') 5 Query SELECT LAST_INSERT_ID() 020327 13:44:32 4 Quit 5 Quit INSERT INTO 〜 と SELECT LAST_INSERT_ID() は、 同じ接続(Id=5)になっています。 しかし、この方法では、パラメータクエリの意味がなくなってしまいます。 # 以前、多量のデータを INSERT する処理を繰り返していたとき、原因不明 # のエラーが発生し、それをパラメータクエリに置き換えたところ解決した # ということがあったので、パラメータクエリは使いたいのです。 そこで、教えていただきたいのは、 ・Delphi の TSQLConnection.MaxStmtsPerConn に相当する、 「1つの接続を使って実行できる文の数に対する制限」を変更する方法が、 MySQL に用意されていませんでしょうか? ・もっといい別の方法があったら教えていただけないでしょうか? 例えば、INSERT したら LAST_INSERT_ID を返すようなことができれば、 速度面でも有利かと思うのですが・・・。 よろしく、お願いします。 ■□ システムプロモート 黒田 □■ kuroda@xxxxxxxxxx