Cách lấy id tăng tự động tiếp theo trong mysql


113

Cách lấy id tiếp theo trong mysql để chèn nó vào bảng

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

1
sử dụng một auto_incrementcột
đan vào

Bạn muốn id tiếp theo hay id của hàng mà bạn hiện đang chèn? Tức là id ở cuối mã thanh toán có phải là id của hàng lưu mã thanh toán không?
Mike

id của hàng mà tôi hiện đang chèn
faressoft

6
Trong trường hợp đó, hãy nối các giá trị khi bạn truy xuất chúng, không phải khi bạn chèn chúng. Theo cách đó dễ dàng hơn nhiều và bạn loại trừ việc nhận sai id hoặc phải chạy cập nhật - hãy nghĩ điều gì sẽ xảy ra nếu hàng bạn vừa chèn được một ứng dụng khách khác yêu cầu, trước khi bản cập nhật có cơ hội chạy: ứng dụng khách sẽ kết thúc với một mã thanh toán không hợp lệ. Trên một hệ thống có lưu lượng truy cập thấp, điều đó có thể không xảy ra, nhưng tôi không thấy điểm rủi ro.
Mike,

... hoặc như @binaryLV chỉ ra, khóa tài nguyên cũng có thể giải quyết vấn đề. Xem: dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Mike

Câu trả lời:


12

Sử dụng LAST_INSERT_ID()từ truy vấn SQL của bạn.

Hoặc là

Bạn cũng có thể sử dụng mysql_insert_id()để lấy nó bằng PHP.


13
@Sarfraz: Câu hỏi là về id TIẾP THEO không phải là CUỐI CÙNG như bạn nói đã đề cập LAST_INSERT_ID().
Felipe Pereira

1
Nếu hàng được xóa trong bảng tối đa sẽ là sai lầm
peterchaula

chỉ là một lưu ý từ '17 - mysql * chức năng đang bị phản đối - trên có thể được thực hiện vớimysqli_insert_id
treyBake

ai đã đánh dấu đây là câu trả lời? câu hỏi là về id chèn tiếp theo không phải là cuối cùng.
Amit Shah,

252

Bạn có thể dùng

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

hoặc nếu bạn không muốn sử dụng information_schema, bạn có thể sử dụng

SHOW TABLE STATUS LIKE 'table_name'

Cảm ơn vì hai tùy chọn đầu tiên .. Nhưng tùy chọn thứ ba chỉ là số hai được gọi từ PHP .. Không chắc chắn điều gì làm cho điều đó nhanh hơn trên cơ sở dữ liệu lớn ...
Gerard ONeill

1
@GerardONeill Đã xóa nó
ravi404

3
bởi vì một bộ đệm được sử dụng để truy xuất dữ liệu từ information_schema.tables, giải pháp này không hoạt động nữa đối với mysql 8.
Bruno

1
@Bruno bạn có thể đăng bài tham khảo không?
mvorisek

1
Trạng thái tài liệu chính thức TABLES.AUTO_INCREMENTnày được lưu trong bộ nhớ cache dev.mysql.com/doc/refman/8.0/en/… . Blog Mysql cũng có một số bài đăng về nó, nhưng hệ thống có thể sử dụng được mà họ đề cập có vẻ lỗi thời: mysqlserverteam.com/… mysqlserverteam.com/…
Bruno

50

Bạn có thể nhận được giá trị tự động tăng tiếp theo bằng cách thực hiện:

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

Lưu ý rằng bạn không nên sử dụng điều này để thay đổi bảng, thay vào đó hãy sử dụng cột auto_increment để làm điều đó tự động.
Vấn đề là đó last_insert_id()là hồi cứu và do đó có thể được đảm bảo trong kết nối hiện tại.
Em bé này có triển vọng và do đó không phải là duy nhất cho mỗi kết nối và không thể dựa vào.
Chỉ trong một cơ sở dữ liệu kết nối duy nhất thì nó mới hoạt động, nhưng các cơ sở dữ liệu kết nối đơn ngày nay có thói quen trở thành nhiều cơ sở dữ liệu kết nối vào ngày mai.

Xem: SHOW TABLE STATUS


5
Tôi không tán thành nó, nhưng vấn đề với việc cố gắng sử dụng giá trị tăng tự động cuối cùng là nó có thể không phải là giá trị cuối cùng vào thời điểm bạn sử dụng nó - bất kể việc CHỌN và CHÈN tiếp theo được thực hiện nhanh như thế nào.
Mike,

@Mike, điều gì sẽ xảy ra nếu nó được thực hiện trong một truy vấn? Một cái gì đó như thế insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'nào? Tôi sẽ sử dụng cập nhật trong after insertkích hoạt và last_insert_id(), mặc dù ...
binaryLV

1
@binaryLV: Khoảng cách giữa SELECT và INSERT càng nhỏ thì khả năng giá trị thay đổi càng nhỏ, nhưng không loại trừ hoàn toàn. Hãy tưởng tượng một hệ thống có hàng nghìn lượt truy cập mỗi phút trên cơ sở dữ liệu - khả năng giá trị đã thay đổi sẽ tăng lên đáng kể. Việc khóa bảng hoặc hàng có thể ngăn chặn điều này nếu nó được thực hiện dưới dạng một truy vấn đơn lẻ, nhưng điều đó dựa trên một hành vi cụ thể của công cụ cơ sở dữ liệu mà có thể không được ghi lại đầy đủ. Tôi sẽ đi với phần tiếp theo UPDATEnếu tôi cũng vậy. Nhưng tôi chỉ muốn kết hợp cả hai tại thời điểm hiển thị và tiết kiệm mọi rắc rối.
Mike,

3
SHOW TABLE STATUSmong đợi để xem database namesau FROM'table name pattern'sau LIKE.
x-yuri

2
bởi vì một bộ đệm được sử dụng để truy xuất dữ liệu từ information_schema.tables, giải pháp này không hoạt động nữa đối với mysql 8.
Bruno

15

Điều này sẽ trả về giá trị tăng tự động cho cơ sở dữ liệu MySQL và tôi đã không kiểm tra với các cơ sở dữ liệu khác. Xin lưu ý rằng nếu bạn đang sử dụng bất kỳ cơ sở dữ liệu nào khác, thì cú pháp truy vấn có thể khác.

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

CHỌN AUTO_INCREMENT TỪ information_schema.tables WHERE table_name = 'your_table_name' and table_schema = 'your_database_name';
LJay

10

Câu trả lời hàng đầu sử dụng PHP MySQL_ cho một giải pháp, tôi nghĩ rằng tôi sẽ chia sẻ một giải pháp PHP MySQLi_ được cập nhật để đạt được điều này. Không có lỗi đầu ra trong bản đồ này!

$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'];

Bắt đầu gia số Tự động tiếp theo sắp xuất hiện trong bảng.


bởi vì một bộ đệm được sử dụng để truy xuất dữ liệu từ information_schema.tables, giải pháp này không hoạt động nữa đối với mysql 8.
Bruno

9

Trong PHP, bạn có thể thử điều này:

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

HOẶC LÀ

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

5
Hãy lưu ý với phương pháp đầu tiên nếu bản ghi có id cao nhất bị xóa, sau đó bạn sẽ tạo một bản ghi mới với id mà bản ghi đã bị loại bỏ từng có.
Tom Jenkinson

và nếu các khoá trước đó đã được sử dụng trong các bảng khác và vẫn giữ ở đó bạn có thể kết thúc với phép thuật rất lạ
Tebe

cái đầu tiên trả về sai id nếu bạn thả bản ghi được chèn lần cuối,
Ali Parsa

6

Giải pháp:

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" là tên của Cơ sở dữ liệu của chúng tôi


5

Truy vấn đơn giản sẽ làm được SHOW TABLE STATUS LIKE 'table_name'



3

Bạn không thể sử dụng ID trong khi chèn, bạn cũng không cần nó. MySQL thậm chí không biết ID khi bạn đang chèn bản ghi đó. Bạn chỉ có thể lưu "sahf4d2fdd45"trong payment_codebảng và sử dụng idpayment_codesau này.

Nếu bạn thực sự cần mã thanh toán của mình để có ID trong đó thì hãy CẬP NHẬT hàng sau phần chèn để thêm ID.


+1 Để làm cho điều này rõ ràng hơn một chút: nếu bạn lấy giá trị 'mới nhất' từ một cột, nó chỉ được đảm bảo là giá trị mới nhất tại thời điểm chính xác bạn lấy nó. Nó có thể không phải là giá trị mới nhất khi bạn sử dụng giá trị đó trong lần chèn tiếp theo. Trong trường hợp cột tăng tự động, luôn có khả năng một giá trị khác đã được thêm vào giữa thời điểm bạn truy xuất id và thời điểm bạn chèn nó vào nơi khác. Nếu bạn đang tham chiếu đến một hàng mà bạn vừa chèn, sử dụng LAST_INSERT_ID () là tốt. Nếu bạn đang cố gắng đảm bảo một giá trị duy nhất, thì không phải vậy.
Mike,

@cularis, MySQL không biết id auto_increment tiếp theo, nó được liệt kê trong information_schema.tablesbảng.
Johan

1
@faressoft: Nếu ý tưởng là có mã thanh toán bao gồm một chuỗi duy nhất cộng với id của hàng chứa mã thanh toán đó, chỉ cần kết hợp cả hai khi bạn truy xuất hàng - với một SELECT ... CONCAT(payment_code, id)hoặc trong mã ứng dụng của bạn. Bạn thậm chí có thể bọc SELECTtrong một VIEW, để bạn luôn trả về giá trị phù hợp mà không phải lo lắng về CONCAT trong mỗi lần CHỌN từ ứng dụng của bạn.
Mike,

3

Bạn cần ID gia tăng tiếp theo để làm gì?

MySQL chỉ cho phép một trường tăng tự động trên mỗi bảng và nó cũng phải là khóa chính để đảm bảo tính duy nhất.

Lưu ý rằng khi bạn nhận được ID chèn tiếp theo, nó có thể không khả dụng khi bạn sử dụng vì giá trị bạn có chỉ nằm trong phạm vi của giao dịch đó. Do đó, tùy thuộc vào tải trên cơ sở dữ liệu của bạn, giá trị đó có thể đã được sử dụng vào thời điểm yêu cầu tiếp theo đến.

Tôi khuyên bạn nên xem lại thiết kế của mình để đảm bảo rằng bạn không cần biết giá trị tăng tự động nào sẽ chỉ định tiếp theo


Không phải là một ý kiến ​​hay nếu giả sử loại ứng dụng yêu cầu ID. Có những ứng dụng như ứng dụng tôi đang làm vào lúc này cần ID gia tăng tiếp theo và giá trị được truy xuất không có nguy cơ bị phân bổ cho tập lệnh khác.
JG Estiot,

3

Tôi đề nghị suy nghĩ lại những gì bạn đang làm. Tôi chưa bao giờ trải qua một trường hợp sử dụng duy nhất nào mà kiến ​​thức đặc biệt đó được yêu cầu. Id tiếp theo là một chi tiết triển khai rất đặc biệt và tôi sẽ không tính đến việc nhận được nó là ACID an toàn.

Thực hiện một giao dịch đơn giản cập nhật hàng đã chèn của bạn với id cuối cùng:

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;

Tôi có thể nói với một trường hợp sử dụng như vậy, tôi đang cố gắng chẩn đoán sự cố sản xuất, vì vậy tôi cần tìm hiểu xem hàng cuối cùng trong bảng có thực sự là hàng cuối cùng hay không hoặc có một hàng được thêm vào sau đó bằng cách nào đó đã bị xóa, bảng có trường auto_increment trong đó, vì vậy bằng cách tìm thông tin này, tôi có thể kết luận xem hàng đã bị xóa hay không bao giờ được thêm vào.
Usman

1
Điều đó có thể phù hợp với bạn, nhưng tôi sẽ không dựa vào điều đó vì tôi không nghĩ rằng bạn có bất kỳ đảm bảo nào về điều đó: dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html " khi cột AUTO_INCREMENT là một phần của chỉ mục nhiều cột), các giá trị AUTO_INCREMENT được sử dụng lại nếu bạn xóa hàng có giá trị AUTO_INCREMENT lớn nhất trong bất kỳ nhóm nào. "
Markus Malkusch

Cảm ơn, thông tin hữu ích, cũng như auto_increment liên kết được chia sẻ của bạn có thể được đặt lại bằng cách chèn một số theo cách thủ công, vì vậy có không đáng tin cậy.
Usman

2

Bạn phải kết nối với MySQL và chọn cơ sở dữ liệu trước khi có thể thực hiện việc này

$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

sử dụng "mysql_insert_id ()". mysql_insert_id () hoạt động trên truy vấn được thực hiện gần đây nhất, hãy nhớ gọi mysql_insert_id () ngay sau khi truy vấn tạo ra giá trị.

Dưới đây là ví dụ sử dụng:

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

Tôi hy vọng ví dụ trên là hữu ích.


Cảm ơn tôi biết về nó.
Mr.Javed Multani


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

Mặc dù tôi nghi ngờ về năng suất của nó nhưng nó đáng tin cậy 100%


Tôi cũng đồng ý rằng đây là cách tiếp cận đơn giản nhất. Không chắc tại sao bạn bị bỏ phiếu thấp, nhưng tôi sẽ bù đắp bằng một phiếu ủng hộ.
lặp lại

Tôi đã không đề cập đến sự cần thiết của giao dịch, nếu bạn không bọc nó bên trong giao dịch, mã này sẽ tệ càng sớm càng tốt, nó đáp ứng tải thực.
Tebe

1
Điều gì sẽ xảy ra nếu hàng mới nhất bị xóa? Hoặc nhiều hàng mới nhất đã bị xóa?
Liam W

Không vấn đề, chìa khóa giải thoát không quen, trừ khi bạn xác định nó một cách rõ ràng
Tebe

1

sử dụng câu trả lời của 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

sử dụng trong truy vấn chèn của bạn, để tạo SHA1 Hash. Ví dụ.:

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

Điều này luôn luôn hoạt động? Có điều kiện đua nếu hai lần chèn diễn ra cùng một lúc không?
Jmons

0

Cải tiến của @ ravi404, trong trường hợp bù đắp tự động của bạn KHÔNG PHẢI là 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): công cụ db dường như sẽ cân nhắc mức bù là 1. Vì vậy, bạn cần loại bỏ giả định này, sau đó thêm giá trị tùy chọn của @@ auto_increment_offset hoặc mặc định thành 1: IFNULL (@@ auto_increment_offset, 1)


0

Đối với tôi, nó hoạt động và trông đơn giản:

 $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

Không cần thiết phải chỉ định $last_idlặp đi lặp lại khi bạn có thể DESC. whileKhối của bạn đã làm vô số công việc vô ích.
Tiw

vâng, đúng ... Tôi vừa mới nhận ra nó không hoàn thiện ... :( cuối người ta có thể lặp lại các id, nếu nó đã bị xóa trước khi ... :(
Toncsiking

0

Nếu trả về không đúng AUTO_INCREMENT, hãy thử:

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

Xóa bộ nhớ cache cho bảng, trong BD

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.