MySQL LAST_INSERT_ID ()

151

Eu tenho uma pergunta do MySQL que acho que deve ser bastante fácil. Preciso retornar o LAST INSERTED ID da tabela1 quando executo a seguinte consulta 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();

Como você pode entender, o código atual retornará apenas o ID da ÚLTIMA INSERÇÃO da tabela2 em vez da tabela1, como posso obter o ID da tabela1 mesmo se eu inserir na tabela2 entre?

Martin
fonte

Respostas:

248

Você pode armazenar o último ID de inserção em uma variável:

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

Ou obtenha a tabela max frm id1

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;   
Julien Hoarau
fonte
5
Obrigado! Não o fiz funcionar primeiro, pois estava usando o asp.net com MySQL e precisava adicionar Allow User Variables = True à String de Conexão para permitir variáveis.
Martin
114
max não é uma boa ideia, pois você pode perder uma corrida com outro dispositivo de inserção.
Rob Starling
5
@RobStarling Eu concordo totalmente, mas no caso de alguém absolutamente precisar; use uma transação com o nível de isolamento adequado.
Aidiakapi
8
e se 2 INSERTOS acontecerem ao mesmo tempo ou um antes do outro?
FosAvance 28/03
32
@FosAvance LAST_INSERT_ID () é ref
Momin Al Aziz
18

Como você realmente armazenou o LAST_INSERT_ID () anterior na segunda tabela, é possível obtê-lo a partir daí:

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();
Artem Goutsoul
fonte
13

Isso permite que você insira uma linha em 2 tabelas diferentes e cria uma referência para as duas tabelas também.

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;
Ospho
fonte
1
Bom tiro na transação.
Kurt Van den Branden
1
Mas: disponível apenas no InnoDB.
21418 Ripple (
4

Eu tive o mesmo problema no bash e estou fazendo algo parecido com isto:

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

que funciona bem :-) Mas

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

não trabalha Porque após o primeiro comando, o shell será desconectado do mysql e novamente registrado para o segundo comando, e a variável @last_insert_id não será mais definida. Minha solução é:

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

Talvez alguém esteja procurando uma solução, uma festança :-)

Eugen Spinne
fonte
LAST_INSERT_IDdisponível apenas para a conexão ativa. #mysqO comando connect para todos os comandos. Você pode se conectar com o mysqlcomando para o servidor e inserir suas perguntas, ou você pode criar um arquivo de texto e você o mysqlcomando com redirecionamento de arquivo txt akamysql [connection option] < txt.file
raiserle
1

Como temos apenas uma pessoa inserindo registros, eu executo a seguinte consulta imediatamente após a inserção:

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

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

            $id = $row['id'];

}

Isso recupera o último ID do banco de dados.

sspence65
fonte
1
Eu tive que dar um exemplo válido, então usei o que eu uso. Se eu tivesse feito isso em C, você provavelmente se queixaram "Nem todo o usa C" ....
sspence65
Provavelmente o mais seguro e mais simples de todos;)
Anjana Silva 11/07
1

Para nenhuma solução InnoDB: você pode usar um procedimento 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

E você pode usá-lo ...

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

Seria possível salvar a variável last_id_in_table1 em uma variável php para usá-la mais tarde?

Com este last_id, preciso anexar alguns registros em outra tabela com este last_id, então preciso:

1) Faça um INSERT e obtenha o last_id_in_table1

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

2) Para qualquer linha indeterminada em outra tabela, ATUALIZE essas linhas com o last_id_insert gerado na inserção.

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

Em vez disso, LAST_INSERT_ID() tente usar este

mysqli_insert_id(connection)
Sambit Kumar Dalai
fonte
-1

Por último e segundo último:

INSERT INTO `t_parent_user`(`u_id`, `p_id`) VALUES ((SELECT MAX(u_id-1) FROM user) ,(SELECT MAX(u_id) FROM user  ) );
user2541471
fonte
Esta solução não é segura fora de uma transação (isto é, habilitada para confirmação automática) e dentro de uma transação com um nível de isolamento de transação abaixo de serializável. Veja: en.wikipedia.org/wiki/Isolation_(database_systems)
snorbi
-2

Apenas para adicionar à postagem de Rodrigo, em vez de LAST_INSERT_ID () na consulta, você pode usar SELECT MAX (id) FROM tabela1 ;, mas você deve usar (),

INSERT INTO table1 (title,userid) VALUES ('test', 1)
INSERT INTO table2 (parentid,otherid,userid) VALUES ( (SELECT MAX(id) FROM table1), 4, 1)
Pavlen
fonte
Esta solução não é segura fora de uma transação (isto é, habilitada para confirmação automática) e dentro de uma transação com um nível de isolamento de transação abaixo de serializável. Veja: en.wikipedia.org/wiki/Isolation_(database_systems)
snorbi
-9

Se você precisar do mysql, após a sua consulta, o último ID incremental automático sem outra consulta, insira seu código:

mysql_insert_id();
Luca Perico
fonte
15
Não recomendamos mysql_ * - essas são obsoleto
German Rumm
cletus obteve 106 upvotes e resposta marcada para mysql_insert_id aqui: stackoverflow.com/a/897361/153923
jp2code
2
cletus respondeu em 2009! O mysql está obsoleto melhor para usar o mysqli e o mysqli_insert_id ie2.php.net/mysqli_insert_id
Maciej Paprocki
2
Luca, se você excluir esta resposta desatualizada, acredito que seus pontos de reputação serão devolvidos.
TecBrat
Outra alternativa válida para a sugestão preterida é DOP :: lastInsertId ( php.net/manual/en/pdo.lastinsertid.php )
w5m