LAST_INSERT_ID () MySQL


151

У меня есть вопрос MySQL, который я думаю, должно быть довольно легко. Мне нужно вернуть LAST INSERTED ID из таблицы 1, когда я запускаю следующий запрос MySql:

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

Как вы понимаете, текущий код будет просто возвращать идентификатор LAST INSERT для table2 вместо table1, как я могу получить идентификатор из table1, даже если я вставлю в table2 между ними?

Ответы:


249

Вы можете сохранить последний идентификатор вставки в переменной:

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

Или получите максимальный идентификатор от table1

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
Спасибо! Сначала я не работал, так как использовал asp.net с MySQL, и мне нужно было добавить Allow User Variables = True в строку подключения, чтобы разрешить использование переменных.
Мартин

114
Макс не очень хорошая идея, так как вы можете проиграть гонку с другим инсертором.
Роб Старлинг

5
@RobStarling Я полностью согласен, но в случае, если это кому-то действительно нужно; используйте транзакцию с надлежащим уровнем изоляции.
Aidiakapi

8
Что делать, если 2 ВСТАВКИ происходят одновременно или один перед другим?
FosAvance

32
@FosAvance LAST_INSERT_ID () - это ссылка на
Gun2sh

18

Поскольку вы фактически сохранили предыдущий LAST_INSERT_ID () во второй таблице, вы можете получить его оттуда:

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

Это позволяет вставить строку в 2 разные таблицы и создать ссылку на обе таблицы.

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
Хороший выстрел по сделке.
Курт Ван ден Бранден

1
Но: доступно только на InnoDB.
Райзер

4

У меня была та же проблема в Bash, и я делаю что-то вроде этого:

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

который отлично работает :-) Но

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

не работает Потому что после первой команды оболочка выйдет из mysql и снова войдет для второй команды, и тогда переменная @last_insert_id больше не будет установлена. Мое решение:

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});"

Может быть, кто-то ищет решение bash :-)


LAST_INSERT_IDдоступно только для активного соединения. #mysq-команда подключения для каждой команды. Вы можете подключиться с помощью mysqlкоманды к серверу и вставить свои запросы, или вы можете создать текстовый файл, и вы mysqlкоманда с перенаправлением из TXT-файла akamysql [connection option] < txt.file
raiserle

1

У нас есть только один человек, который вводит записи, поэтому я выполняю следующий запрос сразу после вставки:

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

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

            $id = $row['id'];

}

Это извлекает последний идентификатор из базы данных.


1
Я должен был привести действительный пример, поэтому я использовал тот, который я использую. Если бы я сделал это в C, вы, вероятно, жаловались бы, что "не каждый использует C" ....
sspence65

Наверное, самый безопасный и простой из всех;)
Анжана Силва

1

Для решения InnoDB нет: вы можете использовать процедуру 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

И вы можете использовать это ...

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

0

Можно ли сохранить переменную last_id_in_table1 в переменную php, чтобы использовать ее позже?

С этим last_id мне нужно прикрепить некоторые записи в другую таблицу с этим last_id, поэтому мне нужно:

1) Сделайте INSERT и получите last_id_in_table1

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

2) Для любых неопределенных строк в другой таблице, ОБНОВИТЬ эти строки с помощью last_id_insert, сгенерированного во вставке.

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


-1

Для последнего и второго последнего:

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

Это решение небезопасно вне транзакции (т. Е. Включена автоматическая фиксация) и внутри транзакции с уровнем изоляции транзакции ниже сериализуемого. Смотрите: en.wikipedia.org/wiki/Isolation_(database_systems)
снорби

-2

Просто чтобы добавить сообщение Родриго, вместо LAST_INSERT_ID () в запросе вы можете использовать SELECT MAX (id) FROM table1 ;, но вы должны использовать (),

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

Это решение небезопасно вне транзакции (т. Е. Включена автоматическая фиксация) и внутри транзакции с уровнем изоляции транзакции ниже сериализуемого. Смотрите: en.wikipedia.org/wiki/Isolation_(database_systems)
снорби

-9

Если вам нужно иметь из mysql, после вашего запроса, последний автоинкрементный идентификатор без другого запроса, вставьте в ваш код:

mysql_insert_id();

15
Не рекомендую mysql_ * - они устарели
немецкий Рам

Клет получил 106 голосов и отметил ответ для mysql_insert_id здесь: stackoverflow.com/a/897361/153923
jp2code

2
Клетус ответил на это в 2009 году! mysql не рекомендуется использовать mysqli и mysqli_insert_id ie2.php.net/mysqli_insert_id
Maciej Paprocki

2
Лука, если ты удалишь этот устаревший ответ, я верю, что твои очки репутации будут возвращены.
TecBrat

Другая действительная альтернатива устаревшему предложению - PDO :: lastInsertId ( php.net/manual/en/pdo.lastinsertid.php )
w5m
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.