วิธีรับรหัสการเพิ่มอัตโนมัติถัดไปใน mysql


114

วิธีรับ id ถัดไปใน mysql เพื่อแทรกในตาราง

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

1
ใช้auto_incrementคอลัมน์
knittl

คุณต้องการรหัสถัดไปหรือรหัสของแถวที่คุณกำลังแทรกอยู่? นั่นคือรหัสท้ายรหัสการชำระเงินควรเป็นรหัสของแถวที่เก็บรหัสการชำระเงินหรือไม่
ไมค์

id ของแถวที่ฉันกำลังแทรกอยู่
faressoft

6
ในกรณีนั้นให้เชื่อมต่อค่าเมื่อคุณดึงข้อมูลไม่ใช่เมื่อคุณแทรก วิธีนี้ง่ายกว่ามากและคุณจะไม่ได้รับรหัสที่ไม่ถูกต้องหรือต้องเรียกใช้การอัปเดต - คิดว่าจะเกิดอะไรขึ้นถ้าแถวที่คุณเพิ่งแทรกถูกร้องขอโดยไคลเอนต์อื่นก่อนที่การอัปเดตจะมีโอกาสทำงาน: ไคลเอนต์ จะลงเอยด้วยรหัสการชำระเงินที่ไม่ถูกต้อง ในระบบที่มีการจราจรน้อยสิ่งนั้นอาจไม่เกิดขึ้น แต่ฉันไม่เห็นจุดที่จะเสี่ยง
Mike

... หรือตามที่ @binaryLV ชี้ให้เห็นการล็อกทรัพยากรอาจช่วยแก้ปัญหาได้เช่นกัน ดู: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

คำตอบ:


12

ใช้LAST_INSERT_ID()จากแบบสอบถาม SQL ของคุณ

หรือ

คุณยังสามารถใช้mysql_insert_id()เพื่อรับมันโดยใช้ PHP


13
@Sarfraz: คำถามคือเกี่ยวกับNEXTรหัสไม่ได้เป็นครั้งสุดท้ายLAST_INSERT_ID()ที่คุณกล่าวว่าการกล่าวขวัญ
Felipe Pereira

1
หากแถวถูกลบในตารางค่าสูงสุดจะผิด
peterchaula

เพิ่งทราบจาก '17 - ฟังก์ชัน mysql * เลิกใช้งานแล้ว - ข้างต้นสามารถทำได้ด้วยmysqli_insert_id
treyBake

ใครทำเครื่องหมายนี้เป็นคำตอบ คำถามเกี่ยวกับการใส่รหัสถัดไปไม่ใช่ครั้งสุดท้าย
Amit Shah

253

คุณสามารถใช้ได้

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

หรือหากคุณไม่ต้องการใช้ information_schema คุณสามารถใช้สิ่งนี้ได้

SHOW TABLE STATUS LIKE 'table_name'

ขอบคุณสำหรับสองตัวเลือกแรก .. แต่ตัวที่สามเป็นเพียงหมายเลขสองที่เรียกจาก PHP .. ไม่แน่ใจว่าอะไรทำให้เร็วขึ้นในฐานข้อมูลขนาดใหญ่ ...
Gerard ONeill

1
@GerardONeill ลบออก
ravi404

3
เนื่องจากแคชถูกใช้เพื่อดึงข้อมูลจาก information_schema.tables โซลูชันนี้จึงไม่สามารถใช้งานได้กับ mysql 8 อีกต่อไป
Bruno

1
@Bruno โพสต์อ้างอิงได้ไหม
mvorisek

1
รัฐนี้เอกสารอย่างเป็นทางการที่TABLES.AUTO_INCREMENTถูกแคช dev.mysql.com/doc/refman/8.0/en/... 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 น้อยลงโอกาสที่ค่าจะเปลี่ยนแปลงก็จะยิ่งน้อยลง แต่ก็ไม่ได้แยกออกอย่างสมบูรณ์ ลองนึกภาพระบบที่มีการเข้าชมหลายพันครั้งต่อนาทีบนฐานข้อมูลโอกาสที่มูลค่าจะเปลี่ยนแปลงเพิ่มขึ้นอย่างมาก การล็อกตารางหรือแถวอาจป้องกันสิ่งนี้ได้หากทำเป็นแบบสอบถามเดียว แต่จะขึ้นอยู่กับลักษณะการทำงานเฉพาะของกลไกจัดการฐานข้อมูลซึ่งอาจไม่ได้รับการบันทึกไว้อย่างดี ฉันจะไปกับครั้งต่อ ๆ ไปUPDATEถ้าฉันมีด้วย แต่ฉันอยากจะเชื่อมทั้งสองอย่างเข้าด้วยกันในเวลาแสดงผลและช่วยประหยัดความยุ่งยากทั้งหมด
ไมค์

3
SHOW TABLE STATUSคาดว่าจะเห็นdatabase nameหลังFROMและหลัง'table name pattern' LIKE
x-yuri

2
เนื่องจากแคชถูกใช้เพื่อดึงข้อมูลจาก information_schema.tables โซลูชันนี้จึงไม่สามารถใช้งานได้กับ mysql 8 อีกต่อไป
Bruno

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();

เลือก AUTO_INCREMENT จาก information_schema.tables WHERE table_name = 'your_table_name' และ table_schema = 'your_database_name';
LJay

10

คำตอบด้านบนใช้ PHP MySQL_สำหรับโซลูชันคิดว่าฉันจะแชร์โซลูชันPHP MySQLi_ ที่อัปเดตเพื่อให้บรรลุสิ่งนี้ ไม่มีผลลัพธ์ข้อผิดพลาดใน exmaple นี้!

$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 อีกต่อไป
Bruno

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 ที่เคยมีมา
Tom Jenkinson

และหากคีย์ก่อนหน้านี้ถูกใช้ในตารางอื่นและยังคงถูกเก็บไว้ที่นั่นคุณสามารถจบลงด้วยเวทมนตร์ที่แปลกประหลาดมาก
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 ในขณะที่แทรกได้และคุณไม่จำเป็นต้องใช้ MySQL ไม่ทราบ ID ด้วยซ้ำเมื่อคุณกำลังแทรกระเบียนนั้น คุณเพียงแค่สามารถบันทึก"sahf4d2fdd45"ในpayment_codeตารางและการใช้งานidและpayment_codeในภายหลัง

หากคุณต้องการให้ payment_code ของคุณมี ID อยู่จริงๆให้อัปเดตแถวหลังแทรกเพื่อเพิ่ม ID


+1 เพื่อให้ชัดเจนยิ่งขึ้น: หากคุณจับค่า 'ล่าสุด' จากคอลัมน์ก็รับประกันได้ว่าจะเป็นค่าล่าสุดในขณะที่คุณคว้ามันเท่านั้น อาจไม่ใช่ค่าล่าสุดเมื่อคุณมาใช้ค่านั้นในการแทรกครั้งต่อ ๆ ไป ในกรณีของคอลัมน์การเพิ่มอัตโนมัติมีโอกาสเสมอที่จะมีการเพิ่มค่าอื่นระหว่างเวลาที่คุณดึงรหัสและเวลาที่คุณแทรกไว้ที่อื่น หากคุณกำลังอ้างอิงแถวที่คุณเพิ่งแทรกการใช้ LAST_INSERT_ID () ก็ใช้ได้ หากคุณพยายามตรวจสอบให้แน่ใจว่ามีค่าที่ไม่ซ้ำกันแสดงว่าไม่ใช่
ไมค์

@cularis, MySQL ทราบรหัส auto_increment ถัดไปซึ่งแสดงอยู่ในinformation_schema.tablesตาราง
โยฮัน

1
@faressoft: หากแนวคิดคือการมีรหัสการชำระเงินที่ประกอบด้วยสตริงที่ไม่ซ้ำกันบวกกับรหัสของแถวที่มีรหัสการชำระเงินนั้นให้รวมทั้งสองเข้าด้วยกันเมื่อคุณเรียกข้อมูลแถว - ด้วย a SELECT ... CONCAT(payment_code, id)หรือในรหัสแอปพลิเคชันของคุณ คุณสามารถรวมเข้าSELECTใน a VIEWเพื่อให้คุณคืนค่าที่ถูกต้องได้เสมอโดยไม่ต้องกังวลเกี่ยวกับ CONCAT ในทุก SELECT จากแอปของคุณ
ไมค์

3

คุณต้องการ ID ที่เพิ่มขึ้นต่อไปสำหรับอะไร?

MySQL อนุญาตให้เพิ่มเขตข้อมูลอัตโนมัติได้เพียงช่องเดียวต่อตารางและต้องเป็นคีย์หลักเพื่อรับประกันความเป็นเอกลักษณ์

โปรดทราบว่าเมื่อคุณได้รับรหัสแทรกถัดไปอาจไม่สามารถใช้ได้เมื่อคุณใช้เนื่องจากมูลค่าที่คุณมีอยู่ภายในขอบเขตของธุรกรรมนั้นเท่านั้น ดังนั้นขึ้นอยู่กับการโหลดบนฐานข้อมูลของคุณค่านั้นอาจถูกใช้ไปแล้วเมื่อมีการร้องขอครั้งต่อไป

ฉันขอแนะนำให้คุณตรวจสอบการออกแบบของคุณเพื่อให้แน่ใจว่าคุณไม่จำเป็นต้องรู้ว่าจะกำหนดค่าการเพิ่มอัตโนมัติใดต่อไป


ไม่ควรสมมติประเภทของแอปพลิเคชันที่ต้องใช้ ID มีแอปพลิเคชันเช่นเดียวกับที่ฉันกำลังทำงานอยู่ในขณะนี้ซึ่งต้องการ ID ที่เพิ่มขึ้นถัดไปและค่าที่ดึงมาจะไม่เป็นอันตรายต่อการจัดสรรให้กับสคริปต์อื่น
JG Estiot

3

ฉันขอแนะนำให้คิดใหม่ว่าคุณกำลังทำอะไรอยู่ ฉันไม่เคยมีประสบการณ์การใช้งานเพียงครั้งเดียวที่จำเป็นต้องมีความรู้พิเศษนั้น รหัสถัดไปเป็นรายละเอียดการใช้งานที่พิเศษมากและฉันจะไม่นับว่าจะได้รับ ACID อย่างปลอดภัย

ทำธุรกรรมง่ายๆเพียงรายการเดียวซึ่งอัปเดตแถวที่คุณแทรกด้วยรหัสสุดท้าย:

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;

ฉันสามารถบอกกรณีการใช้งานดังกล่าวได้ฉันกำลังพยายามวินิจฉัยปัญหาการผลิตดังนั้นฉันจึงต้องหาว่าแถวสุดท้ายในตารางเป็นแถวสุดท้ายจริงๆหรือมีการเพิ่มเข้ามาหลังจากนั้นซึ่งถูกลบไปแล้วหรือไม่ตาราง มีฟิลด์ auto_increment อยู่ในนั้นดังนั้นจากการค้นหาข้อมูลนี้ฉันสามารถสรุปได้ว่าแถวนั้นถูกลบหรือไม่เคยเพิ่ม
Usman

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%


ฉันเห็นด้วยว่านี่เป็นแนวทางที่ง่ายที่สุด ไม่แน่ใจว่าทำไมคุณถึงถูกโหวตลดลง แต่ฉันจะชดเชยด้วยการโหวตเพิ่ม
recurse

ฉันไม่ได้พูดถึงความจำเป็นของการทำธุรกรรมหากคุณไม่ได้รวมไว้ในธุรกรรมรหัสนี้มีหมัดโดยเร็วมันตรงตามการโหลดจริง
Tebe

1
จะเกิดอะไรขึ้นถ้าแถวล่าสุดถูกลบ หรือหลายแถวล่าสุดถูกลบ?
Liam 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 Hash เช่น:

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

สิ่งนี้ได้ผลเสมอหรือไม่? มีเงื่อนไขการแข่งขันหรือไม่หากเม็ดมีดสองอันเกิดขึ้นในเวลาเดียวกัน?
Jmons

0

การปรับปรุง @ ravi404 ในกรณีที่การชดเชยการเพิ่มอัตโนมัติของคุณไม่ใช่ 1:

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ทำงานที่ไร้ประโยชน์มากมาย
ทิว

ใช่ใช่ ... ฉันเพิ่งรู้ว่ามันไม่สมบูรณ์แบบ ... :( ในที่สุดก็สามารถทำซ้ำ 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.