web-dev-qa-db-ja.com

MySQL ON DUPLICATE KEY-最後の挿入ID?

次のクエリがあります。

INSERT INTO table (a) VALUES (0)
  ON DUPLICATE KEY UPDATE a=1

挿入または更新のIDが必要です。 insert_id()は更新されたIDではなく「挿入された」IDのみを返すと信じているため、通常、これを取得するために2番目のクエリを実行します。

2つのクエリを実行せずに行のINSERT/UPDATEおよびIDを取得する方法はありますか?

120
thekevinscott

このページをチェックしてください: https://web.archive.org/web/20150329004325/https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html =
ページの下部で、そのMySQL関数に式を渡すことにより、LAST_INSERT_IDを更新に意味のあるものにする方法を説明します。

MySQLドキュメントの例から:

テーブルにAUTO_INCREMENTカラムが含まれていて、INSERT ... UPDATEが行を挿入する場合、LAST_INSERT_ID()関数はAUTO_INCREMENT値を返します。ステートメントが代わりに行を更新する場合、LAST_INSERT_ID()は意味がありません。ただし、LAST_INSERT_ID(expr)を使用してこの問題を回避できます。 idがAUTO_INCREMENTカラムであると仮定します。 LAST_INSERT_ID()を更新に意味を持たせるには、次のように行を挿入します。

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
156
fredrik

正確に言うと、これが元のクエリの場合:

INSERT INTO table (a) VALUES (0)
 ON DUPLICATE KEY UPDATE a=1

「id」は自動インクリメントの主キーです。これは実際のソリューションです。

INSERT INTO table (a) VALUES (0)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), a=1

すべてここにあります: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

テーブルにAUTO_INCREMENTカラムが含まれていて、INSERT ... UPDATEが行を挿入する場合、LAST_INSERT_ID()関数はAUTO_INCREMENT値を返します。ステートメントが代わりに行を更新する場合、LAST_INSERT_ID()は意味がありません。ただし、LAST_INSERT_ID(expr)を使用してこの問題を回避できます。 idがAUTO_INCREMENTカラムであると仮定します。

32

レコードが存在する場合、基本的には削除/挿入であるREPLACEを確認できます。ただし、これにより、自動インクリメントフィールドが存在する場合は変更され、他のデータとの関係が失われる可能性があります。

2
Brent Baisley

MySQLのバージョンはわかりませんが、InnoDBではautoincにバグがありました

5.1.20のバグおよび5.1.23で修正 http://bugs.mysql.com/bug.php?id=27405

5.1.31のバグおよび5.1.33で修正 http://bugs.mysql.com/bug.php?id=42714

自動インクリメントを使用すると、既存のソリューションが機能します。ユーザーがプレフィックスを定義でき、3000でシーケンスを再起動する必要がある状況があります。このさまざまなプレフィックスのため、自動インクリメントを使用できません。これにより、挿入に対してlast_insert_idが空になります。私は次のように解決しました:

INSERT INTO seq_table (prefix, id) VALUES ('$user_prefix', LAST_INSERT_ID(3000)) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id + 1);
SELECT LAST_INSERT_ID();

プレフィックスが存在する場合、それをインクリメントし、last_insert_idを設定します。プレフィックスが存在しない場合、値3000のプレフィックスが挿入され、last_insert_idに3000が入力されます。

0
Aaron

REPLACEが新しいデータを挿入する前に既存の一致する行を吹き飛ばすことは注目に値しますが、これは明らかかもしれません(ただし、ここではわかりやすくするために言います)。 ON DUPLICATE KEY UPDATEは、指定した列のみを更新し、行を保持します。

manual から:

REPLACEはINSERTとまったく同じように機能しますが、テーブル内の古い行がPRIMARY KEYまたはUNIQUEインデックスの新しい行と同じ値を持つ場合、新しい行が挿入される前に古い行が削除されます。

0
Greg K