LAST_INSERT_ID()、LAST_INSERT_ID(expr)
LAST_INSERT_ID()
に引数を付けない場合は、最近実行された
INSERT
ステートメントの結果として、最初に自動的に生成され、正常に
AUTO_INCREMENT
カラムに挿入された値を表す 64
ビット値が返されます。この値の型は、MySQL
5.6.9 の時点では BIGINT
UNSIGNED、それよりも前では
BIGINT (符号付き)
です。正常に挿入された行がない場合は、LAST_INSERT_ID()
の値は未変更のままです。
LAST_INSERT_ID()
に引数を付けない場合は、MySQL 5.6.9
の時点では符号なし整数、それよりも前では符号付き整数が返されます。
たとえば、AUTO_INCREMENT
値を生成する行を挿入したあとは、次のようにして値を取得できます。
現在実行中のステートメントによって、LAST_INSERT_ID()
の値は影響を受けません。1
つのステートメントで
AUTO_INCREMENT
値を生成してから、独自の
AUTO_INCREMENT
カラムを含むテーブルに行を挿入する複数行の
INSERT ステートメントで
LAST_INSERT_ID()
を参照すると仮定します。LAST_INSERT_ID()
の値は、2
番目のステートメントでも未変更のままです。2
番目以降の行でも、その値は以前に行われた行の挿入による影響を受けません。(ただし、LAST_INSERT_ID()
と
LAST_INSERT_ID(expr)
への参照を混在させると、効果は定義されません。)
以前のステートメントでエラーが返された場合は、LAST_INSERT_ID()
の値が定義されません。トランザクションテーブルでは、エラーによってステートメントがロールバックされる場合、LAST_INSERT_ID()
の値は未定義のままです。手動の
ROLLBACK
では、LAST_INSERT_ID()
の値はトランザクション前の値にリストアされず、ROLLBACK
時点と同じままです。
MySQL 5.6.15
よりも前では、レプリケーションのフィルタ処理ルールが使用されている場合に、この関数が正常にレプリケートされませんでした。(Bug
#17234370、Bug #69861)
ストアドルーチン (プロシージャーや関数)
またはトリガーの本文内では、LAST_INSERT_ID()
の値は、このような種類のオブジェクトの本文外で実行されたステートメントと同様に変更されます。あとに続くステートメントで参照される
LAST_INSERT_ID()
の値でのストアドルーチンまたはトリガーの効果は、ルーチンの種類によって異なります。
ストアドプロシージャーで
LAST_INSERT_ID()
の値を変更するステートメントが実行される場合は、プロシージャー呼び出しが続くステートメントで変更された値が参照されます。
値を変更するストアドファンクションおよびトリガーでは、値は関数やトリガーが終了したときにリストアされ、あとに続くステートメントでは変更された値が参照されません。
生成された ID
は、接続ごとにサーバー内に保持されます。つまり、関数によって指定されたクライアントに返された値は、そのクライアントによって
AUTO_INCREMENT
カラムに影響を与える最近のステートメント用に最初に生成された
AUTO_INCREMENT
値です。この値は、ほかのクライアントが独自の
AUTO_INCREMENT
値を生成した場合でも影響を受ける可能性はありません。この動作によって、各クライアントはほかのクライアントのアクティビティーを気にすることなく、ロックやトランザクションを実行しないで独自の
ID を取得できます。
行の AUTO_INCREMENT
カラムを非「マジック」値
(つまり、NULL でも
0 でもない値)
に設定する場合は、LAST_INSERT_ID()
の値が変更されません。
重要
単一の INSERT
ステートメントを使用して複数の行を挿入する場合、LAST_INSERT_ID()
は、最初に挿入された行のみに対して生成された値を返します。この理由は、ほかの一部のサーバーに対して同じ
INSERT
ステートメントを簡単に再現できるようにするためです。
例:
2 番目の INSERT
ステートメントで 3 つの新しい行が
t
に挿入されましたが、これらの行の 1
番目に生成された ID は 2
であり、あとに続く
SELECT
ステートメントでも、この値が
LAST_INSERT_ID()
によって返されます。
INSERT
IGNORE
を使用し、その行が無視された場合、LAST_INSERT_ID()
は現在の値から未変更のままです
(接続で正常な INSERT
が実行されていない場合は、0
が返されます)。トランザクショナル以外のテーブルでは、AUTO_INCREMENT
カウンタが増分されません。InnoDB
テーブルでは、innodb_autoinc_lock_mode
が 1 または 2
に設定されている場合は、次の例で示すように
AUTO_INCREMENT が増分されます。
expr が
LAST_INSERT_ID()
への引数として指定されている場合は、その引数の値が関数によって返され、LAST_INSERT_ID()
によって次に返される値として記憶されます。これを使用すると、シーケンスのシミュレーションを行うことができます。
シーケンスカウンタを保持するテーブルを作成し、それを初期化します。
そのテーブルを使用して、次のようにシーケンス番号を生成します。
UPDATE
ステートメントは、シーケンスカウンタを増分し、LAST_INSERT_ID()
への次の呼び出しで更新された値が返されるようにします。SELECT
ステートメントは、その値を取得します。mysql_insert_id()
C API
関数を使用して、値を取得することもできます。セクション23.7.7.37「mysql_insert_id()」を参照してください。
LAST_INSERT_ID()
を呼び出さずに、シーケンスを生成できます。このように関数を使用する有用性は、ID
値が最後に自動的に生成された値として保持されることです。独自のシーケンス値を生成するほかのクライアントと互いに影響しあうことなく、複数のクライアントが
UPDATE
ステートメントを発行し、SELECT
ステートメント (または
mysql_insert_id())
で独自のシーケンス値を取得できるため、マルチユーザーでも安全です。
mysql_insert_id()
関数は、INSERT および
UPDATE
ステートメントのあとにしか更新されないため、SELECT
や
SET
などのその他の SQL
ステートメントを実行したあとに、この C API
関数を使用しても、LAST_INSERT_ID(expr)
の値を取得できません。