MySQLで次の自動インクリメントIDを取得する方法


113

MySQLで次のIDを取得してテーブルに挿入する方法

INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))

1
auto_increment列を使用する
knittl 2011

あなたがしたいですか次の ID、またはあなたが現在挿入されていることを行のIDを?つまり、支払いコードの最後のIDは、支払いコードが格納されている行のIDである必要がありますか?
マイク、

現在挿入している行のID
faressoft

6
その場合、値を挿入するときではなく、取得するときに値を連結します。その方がはるかに簡単で、間違ったIDを取得したり、更新を実行したりする必要がなくなります。更新を実行する前に、挿入したばかりの行が別のクライアントによって要求された場合はどうなるかを考えてください。クライアント無効な支払いコードで終了します。トラフィックの少ないシステムでは発生しない可能性がありますが、リスクを負う意味はわかりません。
マイク

...または@binaryLVが指摘するように、リソースのロックも問題を解決する可能性があります。参照:dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

回答:


12

LAST_INSERT_ID()SQLクエリから使用します。

または

mysql_insert_id()PHPを使用して取得することもできます。


13
@Sarfraz:質問は、あなたが言及したように、最後ではなく次の ID に関するものでした。LAST_INSERT_ID()
フェリペペレイラ

1
テーブルで行が削除された場合、最大値は正しくありません
peterchaula

'17からのメモmysqli_insert_id
-mysql

これを回答としてマークしたのは誰ですか?問題は、最後ではない次の挿入IDについてです。
Amit Shah、

252

使用できます

SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;

または、information_schemaを使用したくない場合は、これを使用できます

SHOW TABLE STATUS LIKE 'table_name'

最初の2つのオプションに感謝します。しかし、3番目はPHPから呼び出される2番目のオプションです。大規模なデータベースでそれが速くなる
理由はわかり

1
@GerardONeillが削除
ravi404

3
キャッシュがINFORMATION_SCHEMA.TABLESからデータを取得するために使用されているため、この解決策は、MySQL 8のためのより多くの仕事をしていない
ブルーノ

1
@Brunoに参照を投稿できますか?
mvorisek

1
dev.mysql.com/doc/refman/8.0/en/…にTABLES.AUTO_INCREMENTキャッシュされるこの公式のドキュメントの状態 。:MySQLはそれについていくつかの記事を持っているが、彼らは言及システムvaraibleが古いと思われるもブログmysqlserverteam.com/...のmysqlserverteam.com/...
ブルーノ

50

次のようにして、次の自動インクリメント値を取得できます。

SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'

これを使用してテーブルを変更するべきではないことに注意してください。代わりにauto_incrementカラムを使用して自動的に変更してください。
問題は、それlast_insert_id()が遡及的であるため、現在の接続内で保証できることです。
この赤ちゃんは将来性があり、したがって接続ごとに一意ではなく、信頼することはできません。
単一の接続データベースでのみ機能しますが、今日の単一の接続データベースは、明日は複数の接続データベースになる傾向があります。

見る: SHOW TABLE STATUS


5
私はそれに反対票を投じませんでしたが、最後の自動インクリメント値を使用しようとすることの問題は、SELECTとそれに続くINSERTがどれだけ速く実行されても、それを使用するようになるまでに最後の値ではない可能性があることです。
マイク

@マイク、それが単一のクエリで行われた場合はどうなりますか?のようなものinsert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'?私はafter insertトリガーで更新を使用します、そしてlast_insert_id()...
binaryLV

1
@binaryLV:SELECTとINSERTの間のギャップが小さいほど、値が変更される可能性は低くなりますが、完全に除外されるわけではありません。データベースで1分あたり数千のヒットがあるシステムを想像してみてください。値が変化する可能性は劇的に増加します。テーブルまたは行のロックは、単一のクエリとして行われる場合、これを防ぐことができますが、十分に文書化されていない可能性があるデータベースエンジンの特定の動作に依存しています。私UPDATEも持っていれば次々と行くと思います。ただし、表示時に2つを連結するだけで、面倒な作業はすべて省きます。
マイク

3
SHOW TABLE STATUSdatabase nameFROM'table name pattern'後を見ることを期待していますLIKE
x-yuri 2014

2
キャッシュがINFORMATION_SCHEMA.TABLESからデータを取得するために使用されているため、この解決策は、MySQL 8のためのより多くの仕事をしていない
ブルーノ

15

これはMySQLデータベースの自動インクリメント値を返すため、他のデータベースでは確認していません。他のデータベースを使用している場合は、クエリ構文が異なる場合があることに注意してください。

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = 'your_database_name';

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = database();

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'your_table_name' and table_schema = 'your_database_name';
LJay

10

一番上の答えは、PHP MySQL_をソリューションに使用していますが、これを実現するために更新されたPHP MySQLi_ソリューションを共有します。この例ではエラー出力はありません!

$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();

echo $row['Auto_increment'];

テーブルに現れる次の自動増分をキックアウトします。


キャッシュがINFORMATION_SCHEMA.TABLESからデータを取得するために使用されているため、この解決策は、MySQL 8のためのより多くの仕事をしていない
ブルーノ

9

PHPではこれを試すことができます:

$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;

または

$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];

5
最も高いIDのレコードがドロップされた場合、最初のメソッドに注意してください。次に、ドロップされたレコードが持っていたIDで新しいレコードを作成します。
トムジェンキンソン

以前のキーが別のテーブルで使用され、まだそこに保持されている場合は、非常に奇妙な魔法に終わる可能性があります
Tebe

最後に挿入されたレコードをドロップすると、最初のレコードは間違ったIDを返します
Ali Parsa

6

解決:

CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
  FOR EACH ROW
BEGIN

SELECT  AUTO_INCREMENT Into @xId
    FROM information_schema.tables
    WHERE 
    Table_SCHEMA ="DataBaseName" AND
    table_name = "payments";

SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",@xId);

END;

「DataBaseName」はデータベースの名前です




3

挿入時にIDを使用することはできません。また、IDは必要ありません。MySQLは、そのレコードを挿入するときにIDさえ知りません。テーブルに保存"sahf4d2fdd45"して、後でpayment_code使用することもできます。idpayment_code

本当にpayment_codeにIDを含める必要がある場合は、挿入後に行を更新してIDを追加します。


+1これをもう少し明示的にするために、列から「最新」の値を取得する場合、取得した瞬間の最新の値であることが保証されます。後続の挿入でその値を使用するようになると、最新の値にならない場合があります。自動インクリメント列の場合、IDを取得してから別の場所に挿入するまでの間に別の値が追加される可能性は常にあります。挿入したばかりの行を参照している場合は、LAST_INSERT_ID()を使用すると問題ありません。一意の値を確保しようとしている場合、そうではありません。
マイク

@ cularis、MySQLは次のauto_increment IDを知っていinformation_schema.tablesます。これは表にリストされています。
ヨハン

1
@faressoft:アイデアが、一意の文字列とその支払いコードを含む行のIDで構成される支払いコードを持つことである場合、行を取得するときに2つを組み合わせるだけSELECT ... CONCAT(payment_code, id)です。をでラップSELECTしてVIEW、アプリからのすべてのSELECTのCONCATを気にすることなく、常に正しい値を返すようにすることもできます。
マイク

3

次の増分IDは何のために必要ですか?

MySQLはテーブルごとに1つの自動インクリメントフィールドのみを許可し、一意性を保証するための主キーでもある必要があります。

次の挿入IDを取得するとき、使用する値はそのトランザクションのスコープ内にあるため、使用できない場合があることに注意してください。したがって、データベースの負荷に応じて、その値は次のリクエストが届くまでにすでに使用されている可能性があります。

次に割り当てる自動インクリメント値を知る必要がないことを確認するために、設計をレビューすることをお勧めします


IDを必要とする種類のアプリケーションを想定することはお勧めできません。私が現在取り組んでいるような、次の増分IDを必要とするアプリケーションがあり、取得した値が別のスクリプトに割り当てられる危険はありません。
JG Estiot 2016年

3

私はあなたが何をしているかを再考することを提案します。その特別な知識が必要な単一のユースケースを経験したことはありません。次のIDは非常に特別な実装の詳細であり、ACIDで安全であることを期待することはできません。

挿入された行を最後のIDで更新する単純なトランザクションを1つ作成します。

BEGIN;

INSERT INTO payments (date, item, method)
     VALUES (NOW(), '1 Month', 'paypal');

UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
     WHERE id = LAST_INSERT_ID();

COMMIT;

私はそのようなユースケースの1つを知ることができます、私は生産の問題を診断しようとしているので、テーブルの最後の行が本当に最後の行であるかどうか、または何らかの理由で削除された後に追加されたものがあるかどうかを調べる必要があります。テーブルauto_incrementフィールドが含まれているため、この情報を見つけることで、行が削除されたか、追加されなかったかを判断できます。
ウスマン、

1
それはおそらくあなたのために働くかもしれません、しかし私はあなたがそれに保証を持っているとは思わないので私はそれに依存しません:dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " AUTO_INCREMENT列が複数列インデックスの一部である場合、いずれかのグループで最大のAUTO_INCREMENT値を持つ行を削除すると、AUTO_INCREMENT値が再利用されます。」
Markus Malkusch、

ありがとう、有用な情報。共有リンクのauto_incrementをリセットすると、手動で数値を挿入できるので、信頼できない。
Usman、

2

これを行うには、MySQLに接続してデータベースを選択する必要があります。

$table_name = "myTable"; 
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'"); 
$row = mysql_fetch_array($query); 
$next_inc_value = $row["AUTO_INCREMENT"];  

2

「mysql_insert_id()」を使用してください。mysql_insert_id()は最後に実行されたクエリに作用します。値を生成するクエリの直後にmysql_insert_id()を呼び出してください。

以下は使用例です。

<?php
    $link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

mysql_query("INSERT INTO mytable  VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
    ?>

上記の例がお役に立てば幸いです。


ありがとうございます。
Mr.Javed Multani


1
SELECT id FROM `table` ORDER BY id DESC LIMIT 1

生産性は疑わしいですが、100%信頼できます


これも最も簡単なアプローチであることに同意します。なぜ反対票が投じられたのかはわかりませんが、反対票を差し上げます。
再帰

トランザクションの必要性については触れませんでした。トランザクション内でラップしないと、このコードは実際のロードに見合うように最悪です。
Tebe

1
最新の行が削除された場合はどうなりますか?または、複数の最新の行が削除されましたか?
リアムW

発行しない、解放されたキーは、明示的に指定しない限り使用されません
Tebe

1

ravi404の答えを使用して:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

挿入クエリで使用して、SHA1ハッシュを作成します。例:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( getAutoincrementalNextval ('document') ),
    'Title',
    'Body'
);

これは常に機能しますか?2つの挿入が同時に発生した場合、競合状態はありますか?
Jmons、2016年

0

自動増分オフセットが1でない場合の@ ravi404の改善:

SELECT (`auto_increment`-1) + IFNULL(@@auto_increment_offset,1) 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );

auto_increment-1):dbエンジンは常に1のオフセットを考慮しているようです。そのため、この仮定を破棄し、@@ auto_increment_offsetのオプション値、またはデフォルトの1を追加する必要があります:IFNULL(@@ auto_increment_offset、1)


0

私にとってはうまくいき、シンプルに見えます:

 $auto_inc_db = mysql_query("SELECT * FROM my_table_name  ORDER BY  id  ASC ");
 while($auto_inc_result = mysql_fetch_array($auto_inc_db))
 {
 $last_id = $auto_inc_result['id'];
 }
 $next_id = ($last_id+1);


 echo $next_id;//this is the new id, if auto increment is on

$last_idできれば、繰り返し割り当てる必要はまったくありませんDESC。あなたのwhileブロックはたくさんの無駄な仕事をしました。
Tiw

はい、右...私はちょうどそれが完璧ではない... :(それは前に削除された場合は、1つは、IDを繰り返すことができ、エンド気付きました... :(
Toncsiking

0

正しいAUTO_INCREMENTが返されない場合は、試してください。

ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');

このBDのテーブルのキャッシュをクリア

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.