LAST_INSERT_ID () MySQL


151

Tôi có một câu hỏi MySQL mà tôi nghĩ phải khá dễ. Tôi cần trả về ID CHỨNG NHẬN CUỐI CÙNG từ bảng1 khi tôi chạy truy vấn MySql sau:

INSERT INTO table1 (title,userid) VALUES ('test',1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT LAST_INSERT_ID();

Như bạn có thể hiểu mã hiện tại sẽ trả về ID LAST INSERT của bảng2 thay vì bảng1, làm cách nào tôi có thể lấy id từ bảng1 ngay cả khi tôi chèn vào bảng2 giữa?

Câu trả lời:


248

Bạn có thể lưu trữ id chèn cuối cùng trong một biến:

INSERT INTO table1 (title,userid) VALUES ('test', 1); 
SET @last_id_in_table1 = LAST_INSERT_ID();
INSERT INTO table2 (parentid,otherid,userid) VALUES (@last_id_in_table1, 4, 1);    

Hoặc lấy id tối đa frm bảng1

INSERT INTO table1 (title,userid) VALUES ('test', 1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(), 4, 1); 
SELECT MAX(id) FROM table1;   

5
Cảm ơn! Tôi đã không làm cho nó hoạt động trước tiên khi tôi đang sử dụng asp.net với MySQL và cần thêm Cho phép Biến người dùng = Đúng với Chuỗi kết nối để cho phép các biến.
Martin

114
max không phải là một ý tưởng tốt, vì bạn có thể thua một cuộc đua với một người nội bộ khác.
Rob Starling

5
@RobStarling Tôi hoàn toàn đồng ý, nhưng trong trường hợp ai đó thực sự cần nó; sử dụng một giao dịch với mức cô lập thích hợp.
Aidiakapi

8
Điều gì xảy ra nếu 2 INSERTS xảy ra cùng một lúc hoặc một trước khi khác?
FosAvance

32
@FosAvance LAST_INSERT_ID () là kết nối cụ thể ref
Momin Al Aziz

18

Vì bạn thực sự đã lưu LAST_INSERT_ID () trước đó vào bảng thứ hai, bạn có thể lấy nó từ đó:

INSERT INTO table1 (title,userid) VALUES ('test',1); 
INSERT INTO table2 (parentid,otherid,userid) VALUES (LAST_INSERT_ID(),4,1);
SELECT parentid FROM table2 WHERE id = LAST_INSERT_ID();

13

Điều này cho phép bạn chèn một hàng vào 2 bảng khác nhau và cũng tạo một tham chiếu cho cả hai bảng.

START TRANSACTION;
INSERT INTO accounttable(account_username) 
    VALUES('AnAccountName');
INSERT INTO profiletable(profile_account_id) 
    VALUES ((SELECT account_id FROM accounttable WHERE account_username='AnAccountName'));
    SET @profile_id = LAST_INSERT_ID(); 
UPDATE accounttable SET `account_profile_id` = @profile_id;
COMMIT;

1
Tốt bắn vào giao dịch.
Kurt Van den Branden

Nhưng: chỉ có sẵn trên InnoDB.
raiserle

4

Tôi đã có cùng một vấn đề trong bash và tôi đang làm một cái gì đó như thế này:

mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');"

hoạt động tốt :-) Nhưng

mysql -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');set @last_insert_id = LAST_INSERT_ID();"
mysql -D "dbname" -e "insert into table2 (id_tab1) values (@last_insert_id);"

đừng làm việc Bởi vì sau lệnh đầu tiên, shell sẽ được đăng xuất khỏi mysql và đăng nhập lại cho lệnh thứ hai, và sau đó biến @last_insert_id không được đặt nữa. Giải pháp của tôi là:

lastinsertid=$(mysql -B -N -D "dbname" -e "insert into table1 (myvalue) values ('${foo}');select LAST_INSERT_ID();")
mysql -D "dbname" -e "insert into table2 (id_tab1) values (${lastinsertid});"

Có lẽ ai đó đang tìm kiếm một giải pháp bash :-)


LAST_INSERT_IDchỉ có sẵn cho các kết nối hoạt động. #mysq-command kết nối cho mọi lệnh. Bạn có thể kết nối với mysqllệnh đến máy chủ và chèn truy vấn của mình hoặc bạn có thể tạo tệp văn bản và mysqllệnh đó bằng chuyển hướng từ tệp txt akamysql [connection option] < txt.file
raiserle

1

Chúng tôi chỉ có một người nhập hồ sơ, vì vậy tôi thực hiện truy vấn sau ngay sau khi chèn:

$result = $conn->query("SELECT * FROM corex ORDER BY id DESC LIMIT 1");

while ($row = $result->fetch_assoc()) {

            $id = $row['id'];

}

Điều này lấy id cuối cùng từ cơ sở dữ liệu.


1
Tôi đã phải đưa ra một ví dụ hợp lệ, vì vậy tôi đã sử dụng một ví dụ tôi sử dụng. Nếu tôi đã thực hiện nó trong C, có lẽ bạn đã phàn nàn "không phải ai cũng sử dụng C" ....
sspence65

Có lẽ là an toàn nhất và đơn giản nhất trong số tất cả;)
Anjana Silva

1

Đối với giải pháp không có InnoDB: bạn có thể sử dụng quy trình don't forgot to set the the delimiter for storing the procedure with ;

CREATE PROCEDURE myproc(OUT id INT, IN otherid INT, IN title VARCHAR(255))
BEGIN
LOCK TABLES `table1` WRITE;
INSERT INTO `table1` ( `title` ) VALUES ( @title ); 
SET @id = LAST_INSERT_ID();
UNLOCK TABLES;
INSERT INTO `table2` ( `parentid`, `otherid`, `userid` ) VALUES (@id, @otherid, 1); 
END

Và bạn có thể sử dụng nó ...

SET @myid;
CALL myproc( @myid, 1, "my title" );
SELECT @myid;

0

Có thể lưu biến last_id_in_table1 vào biến php để sử dụng sau này không?

Với last_id này, tôi cần đính kèm một số bản ghi trong một bảng khác với last_id này, vì vậy tôi cần:

1) Thực hiện một INSERT và nhận last_id_in_table1

INSERT into Table1(name) values ("AAA"); 
SET @last_id_in_table1 = LAST_INSERT_ID();

2) Đối với mọi hàng không xác định trong bảng khác, CẬP NHẬT các hàng này với last_id_insert được tạo trong phần chèn.

$element = array(some ids)    
foreach ($element as $e){ 
         UPDATE Table2 SET column1 = @last_id_in_table1 WHERE id = $e 
    }


-1

Đối với cuối cùng và thứ hai cuối cùng:

INSERT INTO `t_parent_user`(`u_id`, `p_id`) VALUES ((SELECT MAX(u_id-1) FROM user) ,(SELECT MAX(u_id) FROM user  ) );

Giải pháp này không an toàn bên ngoài một giao dịch (tức là tự động kích hoạt) và bên trong một giao dịch có mức cô lập giao dịch dưới mức tuần tự hóa. Xem: vi.wikipedia.org/wiki/Isolation_(database_systems)
snorbi

-2

Chỉ cần thêm cho bài đăng Rodrigo, thay vì LAST_INSERT_ID () trong truy vấn, bạn có thể sử dụng CHỌN MAX (id) TỪ bảng1;, nhưng bạn phải sử dụng (),

INSERT INTO table1 (title,userid) VALUES ('test', 1)
INSERT INTO table2 (parentid,otherid,userid) VALUES ( (SELECT MAX(id) FROM table1), 4, 1)

Giải pháp này không an toàn bên ngoài một giao dịch (tức là tự động kích hoạt) và bên trong một giao dịch có mức cô lập giao dịch dưới mức tuần tự hóa. Xem: vi.wikipedia.org/wiki/Isolation_(database_systems)
snorbi

-9

Nếu bạn cần phải có từ mysql, sau truy vấn của bạn, id tự động tăng dần cuối cùng mà không có truy vấn khác, hãy nhập mã của bạn:

mysql_insert_id();

15
Đừng đề nghị mysql_ * - những thứ đó không được dùng nữa
German Rumm

cletus đã nhận được 106 lượt upvote và đánh dấu câu trả lời cho mysql_insert_id tại đây: stackoverflow.com/a/897361/153923
jp2code 13/12/13

2
cletus trả lời nó vào năm 2009! mysql không được chấp nhận tốt hơn khi sử dụng mysqli và mysqli_insert_id tức là2.php.net/mysqli_insert_id
Maciej Paprocki

2
Luca, Nếu bạn xóa câu trả lời lỗi thời này, tôi tin rằng điểm danh tiếng của bạn sẽ được trả lại.
TecBrat

Một sự thay thế hợp lệ để đề nghị NỮA là PDO :: lastInsertId ( php.net/manual/en/pdo.lastinsertid.php )
w5m
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.