web-dev-qa-db-ja.com

MySQL LAST_INSERT_ID()を複数のレコードINSERTステートメントで使用

単一のレコード挿入を実行するループで複数のレコードを挿入する場合、返される最後の挿入IDは、予想どおり、最後のものです。しかし、複数のレコードを挿入するステートメントを実行する場合:

_INSERT INTO people (name,age)
VALUES ('William',25), ('Bart',15), ('Mary',12);
_

上記の3つがテーブルに挿入された最初のレコードであるとしましょう。挿入ステートメントの後、最後の挿入IDが3を返すことを期待していましたが、1を返しました。問題のステートメントの最初の挿入ID。

だから、誰かがこれがLAST_INSERT_ID()の通常の動作であるかどうかを複数のレコードINSERTステートメントのコンテキストで確認してください。だから私はそれに基づいてコードを作ることができます。

39
bogdan

はい。 last_insert_id()のこの動作は MySQLドキュメントに記載されています

重要
単一の INSERT ステートメントを使用して複数の行を挿入した場合、 LAST_INSERT_ID() は最初に挿入された値に対して生成された値を返します行のみ。これは、他のサーバーに対して同じ INSERT ステートメントを簡単に再現できるようにするためです。

41
Asaph

この動作は、MySQLの man page で言及されています。それはコメントにありますが、チャレンジされていませんので、それは予想される動作だと思います。

2
Larry Lustig

テーブルに一意の自動インクリメントカラム(ID)があり、それらをmysql自体から返す必要がない場合は可能だと思います。私はあなたにさらに3つのDBリクエストといくつかの処理を要します。次の手順が必要になります。

  1. 挿入の直前に「Before MAX(ID)」を取得します。
    SELECT MAX(id) AS before_max_id FROM table_name`
  1. データを使用して複数のINSERT ... VALUES()クエリを作成し、それらを保持します。

    INSERT INTO table_name
    (col1, col2)
    VALUES 
    ("value1-1" , "value1-2"), 
    ("value2-1" , "value2-2"), 
    ("value3-1" , "value3-2"), 
    ON DUPLICATE KEY UPDATE
    
  2. 挿入直後に「After MAX(ID)」を取得します。

    SELECT MAX(id) AS after_max_id FROM table_name`
    
  3. 「Before MAX(ID)」と「After MAX(ID)」の間のIDを持つレコードを取得します。

    SELECT * FROM table_name WHERE id>$before_max_id AND id<=$after_max_id`
    
  4. 取得したデータと挿入したデータを照合して照合し、挿入していないレコードを削除します。残りのレコードにはIDがあります。

    foreach ($after_collection as $after_item) {
      foreach ($input_collection as $input_item) {
        if ( $after_item->compare_content($input_item) ) {
          $intersection_array[] = $after_item;
        }
      }
    }

これは、コードの一部を使用して、一般の人が現実の世界でそれを解決する方法です。自動インクリメントのおかげで、チェックするレコードを可能な限り少なくする必要があるため、処理に多くの時間がかかりません。これは最終的な「コピー&ペースト」コードではありません。必要に応じて、独自の関数compare_content()を作成する必要があります。

1
Marcel Zúbrik