[前][次][番号順一覧][スレッド一覧]

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

[前][次][番号順一覧][スレッド一覧]