Obter o novo ID da chave primária do registro na consulta de inserção do mysql?


249

Ok, então vamos dizer que estou fazendo um mysql INSERTem uma das minhas tabelas e a tabela possui a coluna item_idque está definida como autoincremente primary key.

Como faço para que a consulta produza o valor da chave primária recém-gerada item_idna mesma consulta?

Atualmente, estou executando uma segunda consulta para recuperar o ID, mas isso dificilmente parece uma boa prática, considerando que isso pode produzir o resultado errado ...

Se isso não for possível, qual é a melhor prática para garantir a recuperação do ID correto?


1
Não há como retornar algo de uma INSERTconsulta como essa; por que você acha que isso pode produzir o resultado errado?
Comprimidos de explosão

4
Bem, se o processo for executado por duas pessoas separadamente, você poderá obter uma lista de processos sobrepostos, eu acho - já que você precisa executar duas consultas separadas?
Amy Neville


@JimFell sim, é basicamente a mesma pergunta, mas este tem muito melhores respostas em geral
ROZZA

1
Use o postgresql e faça como esta tabela INSERT INTO (col1, col2) VALUES (val1, val2) ID DE RETORNO ou INSERT INTO na tabela (col1, col2) VALUES (val1, val2) RETURNING * ou UPDATE table SET col1 = val1, col2 = val2 ID WHERE declaração RETURNING ou tabela UPDATE SET (col1, col2) = (val1, val2) Declaração WHERE identificação RETURNING ou tabela UPDATE SET (col1, col2) = (val1, col2) = (val1, val2) Declaração WHERE declaração
RETURNING

Respostas:


326

Você precisa usar a LAST_INSERT_ID()função: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Por exemplo:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

Isso fará com que você retorne o PRIMARY KEYvalor da última linha que você inseriu:

O ID que foi gerado é mantido no servidor por conexão . Isso significa que o valor retornado pela função para um determinado cliente é o primeiro valor AUTO_INCREMENT gerado para a instrução mais recente que afeta uma coluna AUTO_INCREMENT por esse cliente .

Portanto, o valor retornado por LAST_INSERT_ID()é por usuário e não é afetado por outras consultas que possam estar sendo executadas no servidor por outros usuários .


8
sim, mas e se nesse ínterim (entre as consultas na lista de processos) alguma outra linha tiver sido inserida? Existe alguma maneira de escrever a consulta de inserção para que ela produza isso?
Amy Neville

Ok, eu vejo ... o último ID de inserção da consulta é gravada, mesmo que não é registrada no resultado ... $ mysqli-> insert_id
Amy Neville

27
Isso fará com que você retorne o PRIMARY KEYvalor da última linha que você inseriu, porque é por conexão - cada conexão com o servidor manterá seu próprio valor para isso. Atualizei a resposta para esclarecer isso.
Duncan Bloqueio

Então, suponha que três usuários postaram seus formulários simultaneamente e meu banco de dados precise inseri-los. Eu quero adicionar uma linha correspondente a cada ID recém-criada da tabela1 na tabela2. A concorrência é resolvida ou terei que fazer isso manualmente em PHP, para solicitações de gravação de banco de dados recebidas?
bad_keypoints 16/09

Se, no momento em que você inserir a tabela1, o banco de dados souber todas as informações que deseja inserir na tabela2, poderá usar um gatilho para fazer isso ou combiná-las em uma consulta. Caso contrário, você precisará usar várias consultas - ou seja, fazê-lo em PHP. Depende do que são os dados e de onde vêm para a segunda inserção.
Duncan Bloqueio

21

Cuidado com o radar !! de "LAST_INSERT_ID ()" se tentar retornar esse valor da chave primária no PHP.

Eu sei que este segmento não está marcado como php, mas para quem encontrou esta resposta que procura retornar um ID de inserção do MySQL a partir de uma inserção com script PHP usando chamadas padrão mysql_query - ele não funcionará e não é óbvio sem capturar erros de SQL.

O mysqli mais recente suporta várias consultas - que LAST_INSERT_ID () é na verdade uma segunda consulta do original.

O IMO, um SELECT separado para identificar a última chave primária, é mais seguro que a função mysql_insert_id () opcional, retornando a ID AUTO_INCREMENT gerada na operação INSERT anterior.


7
LAST_INSERT_IDé uma função MySQL por conexão. Se você consultar o último ID de inserção, é possível que uma conexão separada tenha executado uma gravação e você terá o ID errado.
Pílulas de explosão

O @ExplosionPills mysql_insert_id()também funciona em uma base por conexão, mas também sofre um comportamento estranho, como visto aqui stackoverflow.com/a/897374/1305910 no comentário de Cliffordlife - deixa pra lá que todos nós deveríamos estar usandomysqli
RozzA

você pode esclarecer o que você quer dizer quando fica "não vai funcionar"?
31419 John Ktejik

18

A partir da LAST_INSERT_ID()documentação:

O ID que foi gerado é mantido no servidor por conexão

Ou seja, se você tiver duas solicitações separadas para o script simultaneamente, elas não afetarão as outras LAST_INSERT_ID()(a menos que você esteja usando uma conexão persistente).


2
Eu acho que é duvidoso se a tabela tem um gatilho sobre ele que faz uma inserção em outra tabela .... LAST_INSERT_ID () irá retornar o valor do ID da outra tabela ..
bgies

15

Aqui o que você está procurando !!!

select LAST_INSERT_ID()

Essa é a melhor alternativa de SCOPE_IDENTITY()função usada no SQL Server.

Você também precisa ter em mente que isso só funcionará se Last_INSERT_ID()for acionado pela sua Insertconsulta. Essa é a consulta retorna o ID inserido no esquema. Você não pode obter o último ID inserido da tabela específica.

Para mais detalhes, acesse o link O equivalente à função SQLServer SCOPE_IDENTITY () no mySQL?


6

Se você precisar do valor antes de inserir uma linha:

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

Você pode usar isso em uma inserção:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);

1
Este não parece ser uma boa ideia? Se 2 clientes chamarem essa função ao mesmo tempo, eles acharão que estão inserindo o mesmo ID quando, na realidade, não estiverem ... um será um pouco mais lento na inserção e obterá o próximo ID sem que ele saiba.
CarJul

5

Você receberá estes parâmetros no resultado da sua consulta:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

O insertIdé exatamente o que você precisa.

(NodeJS-mySql)


4

Se em python usando pymysql, no cursor você pode usar cursor.lastrowid


2

basta usar "$ last_id = mysqli_insert_id ($ conn);"


2
Na verdade, eu tropecei aqui procurando a versão php desta resposta graças ao google, então votei nessa resposta. Embora tecnicamente o OP não tenha solicitado php, isso pode ser útil para muitas pessoas que tropeçam aqui também.
Fotógrafo Britt

Muito obrigado Arnav! I
JuanSedano 21/05/19

1

Se você estiver usando PHP: Em um objeto PDO, é possível invocar o método lastInsertId após a inserção.

Caso contrário, com um LAST_INSERT_ID, você poderá obter o valor assim:SELECT LAST_INSERT_ID();



0

Eu só quero compartilhar minha abordagem sobre isso no PHP, alguns de vocês podem achar que não é uma maneira eficiente, mas isso é 100 melhor do que outras opções disponíveis.

gere uma chave aleatória e insira-a na tabela, criando uma nova linha. então você pode usar essa chave para recuperar a chave primária. use a atualização para adicionar dados e fazer outras coisas.

dessa maneira ajuda a proteger uma linha e ter a chave primária correta.

Realmente não recomendo isso, a menos que você não tenha outras opções.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.