MySQL: Inserindo registro e recuperando ID gerado

abril 7, 2009

Um dos grandes problemas que costumo ver no MySQL é o seguinte: “Quero inserir um registro em uma tabela, recuperar o ID que foi gerado pelo AUTO_INCREMENT e inserir registros em outras tabelas.”
Vejo por aí muitas soluções,  algumas interessantes e outras grandes gambiarras.
Esqueça MAX() +1 , ORDER BY chave DESC LIMIT 1, SHOW TABLE STATUS, entre outros…

Segue abaixo uma das melhores formas para se fazer isso:

1 INSERT INTO tabela (chave_primaria, coluna1, coluna2) VALUES (null, aaa, bbb);
2 SELECT LAST_INSERT_ID() INTO @ID;
3 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, xxx, yyy);
4 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, www, zzz);
5 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, uuu, iiii);

Desta forma você tem 100% de eficiência na recuperação do ID, não tendo problemas em capturar um ID recém-inserido por outro usuário. Com LAST_INSERT_ID() você estará recuperando sempre o último ID gerado pela SUA SESSÃO.

Se você estiver usando INNODB engine, ainda pode trabalhar com transações adicionando os comandos START TRANSACTION e COMMIT para ter total integridade dos dados.

[UPDATE]
Este artigo mostra a forma de recuperar um ID recém-gerado através do próprio MySQL, através de comandos SQL.
Muitas pessoas estão perguntando nos comentários sobre como fazer isso em PHP. Segue a dica do leitor Isaque Victor para a utilização da função mysql_insert_id().

Obs: Apesar da função LAST_INSERT_ID() do MySQL e a função mysql_insert_id() do PHP funcionarem de forma parecida, existem algumas situações que podem retornar valores diferentes. Para saber mais: http://dev.mysql.com/doc/refman/5.1/en/mysql-insert-id.html
[/UPDATE]

14 Responses to “MySQL: Inserindo registro e recuperando ID gerado”


  1. Sou novato em php e aind anaum entendo muito bem como as coisas funciona …fiz assim e num deu certo.

    $query = “INSERT INTO `cad` (`id`, `desc1`, `site`, `telefone`, `bairro`,`cidade`,`video`, `endereco`, `imagemlogo`, `palavras`, `tipo`, `data`, `disp`, `nivel`, `posicao`,`nome`, `email`, `categoria1`, `categoria2`, `categoria3`, `categoria4`, `categoria5`) VALUES (”, ‘$desc1’, ‘$site’, ‘$telefone’, ‘$bairro’,’$cidade’,’$video’,’$endereco’, ‘$imagemlogo’, ‘$palavras’, ‘$tipo’, ‘$dataconvertida’, ‘$disp’, ‘$nivel’, ‘posicao’,’$nome’, ‘$email’, ‘$categoria1’, ‘$categoria2’, ‘$categoria3’, ‘$categoria4’, ‘$categoria5′)”;

    $query = ” SELECT LAST_INSERT_ID() INTO `cad` @id “;

    $query = “INSERT INTO `cad_areas` (`id`,`cliente`, `nivel`, `categoria`) VALUES (”,’@id’, ‘$nivel’,’$categoria1′)”;

  2. V4g_Br4Ck3r Says:

    Salvou-me das “adaptações técnicas”(Gambias) aqui!Vlw


  3. tentei sua idéia mas acontece o seguinte, como iniciei uma transação não consigo obter o id sem encerrar a transação do cabeçalho, daí que não consigo atomicidade ao salvar cabeçalho e detalhes. Pois se der commit para o cabeçalho já não fará sentido a transação para manter a integridade caso o detalhe apresente erro, afinal, o cabeçalho já estará comitado.

    • Danilo Akamine Says:

      sinceramente não entendi qual o problema,
      com uma transação aberta isso funciona normalmente.

      START TRANSACTION;
      INSERT INTO cabecalho (id, nome) VALUES (null, ‘Cabecalho’);
      SELECT LAST_INSERT_ID() INTO @ID;
      INSERT INTO detalhes (id, id_cabecalho, texto) VALUES (null, @ID, ‘aaa’);
      INSERT INTO detalhes (id, id_cabecalho, texto) VALUES (null, @ID, ‘bbb’);
      INSERT INTO detalhes (id, id_cabecalho, texto) VALUES (null, @ID, ‘ccc’);
      COMMIT;

      se puder me explicar melhor, podemos descobrir o que está acontecendo.

  4. Artur Says:

    Olá Pessoal, mesmo sendo antigo, segue minha postagem sobre o código que deu certo… Espero ter ajudado alguém com isso:

    // prepara o insert
    $sql_tab1 = “INSERT INTO tabela (`campo1` ,`campo2` ,`campoN`) VALUES (NULL , ‘$campo1’, ‘$campo2’, ‘$campoN’);”;

    // faz o insert
    $cst_insere= mysql_query($sql_tab1);

    //busca o último ID adicionado
    $result = mysql_query(“SELECT LAST_INSERT_ID();”);

    // se a resulta for true pega o ID que foi gerado
    if ($result) {
    $id_registro = mysql_insert_id();
    }
    $id_registro_f = $id_registro; // retira o ID do laço IF

    // monta a 2ª tabela
    $sql_tab2 = “INSERT INTO tabela2 (`campo1` ,`campo2` ,`campoX` ) VALUES (NULL , ‘$id_registro_f’, ‘$campoX’);”;

    Bom.. é isso aí….


    • Artur tentei o seu e o numero do ultimo ID nao recuperava por nada, entao fiz\ gambiarra com a dica inicial e deu certo… Bjinhos meninos

      Segue:
      // prepara o insert
      $sql_tab1 = “INSERT INTO raa_usuarios values (null, ‘”.$usuario.”‘,'”.$email.”‘,'”.$senha.”‘);”;

      // faz o insert
      $cst_insere= mysql_query($sql_tab1);

      //busca o último ID adicionado
      $result = mysql_query(“SELECT LAST_INSERT_ID() INTO @ID”);

      // se a resulta for true pega o ID que foi gerado
      if ($result) {
      $id_registro = mysql_insert_id();
      }
      $id_registro_f = $id_registro; // retira o ID do laço IF

      // monta a 2ª tabela
      $sql_tab2 = “INSERT INTO raa_perfil values (‘”.$na_nome.”‘, ‘”.$no_nome.”‘, ‘”.$na_email.”‘, ‘”.$no_email.”‘, ‘”.$na_celular.”‘, ‘”.$no_celular.”‘, ‘”.$tit_casal.”‘, null, @ID);”;

  5. sugaith Says:

    esse seu modo de inserir esta totalmente errado… em sistemas onde existam centenas de terminais inserindo paralelamente, esta sua solucao seria um desastre…. a probabilidade de um desses terminais inserir um registro no meio da execução dessas duas linhas
    1 INSERT INTO tabela (chave_primaria, coluna1, coluna2) VALUES (null, ‘aaa‘, ‘bbb‘);
    2 SELECT LAST_INSERT_ID() INTO @ID;

    agora, carcule o desastre

    • Danilo Akamine Says:

      Bem, não sei se vc sabe, mas a função LAST_INSERT_ID() retorna o último id gerado pela SUA SESSÃO.
      Se existem milhões de terminais rodando em paralelo, isso não faz diferença, cada terminal terá seu valor próprio no LAST_INSERT_ID() 🙂


  6. Olá pessoal, podem ter certeza que este aqui funciona mesmo para milhões de computadores acessando paralelamente:

    Se você está utilizando php:
    ……………….
    $insertCmd = mysql_query(“INSERT INTO tabela (chave_primaria, coluna1, coluna2) VALUES (null, ‘aaa‘, ‘bbb‘)”);//Esse comando insere

    $idDaInsert = mysql_insert_id($insertCmd);//Esse comando pega o id que foi gerado na inserção acima! valeu
    ………………
    Pronto… só isso. Depois disso você usa a variável $idDaInsert para inserir em outras tabelas ou seja lá o que for.


  7. //$query = ” SELECT LAST_INSERT_ID() INTO `cad` @id “;
    /*Este comando acima, vai pegar o ultimo id inserido. Se algum outro computador inseriu entre o seu comando de inserção e este seu comando de pegar o id, você vai terminar pegando o id errado. Vai pegar o id do outro computador. Em php você vai selecionar exatamente o id que você quer, fazendo o código que eu disse. Repetindo:*/

    $insertCmd = mysql_query(“INSERT INTO tabela (chave_primaria, coluna1, coluna2) VALUES (null, ‘aaa‘, ‘bbb‘)”);//Esse comando insere

    $idDaInsert = mysql_insert_id($insertCmd);//Esse comando pega o id que foi gerado na inserção acima! valeu

  8. Justino Miranda Says:

    ola pessoal, sou novato me ajudem.
    quero inserir na tb_enderecos e depois em tb_alunos e depois em tb_matriculas.
    consigo inserir em tb_enderecos e nas outras tabelas não.
    como posso fazer isso em php.

    create table tb_enderecos(
    cod_end int auto_increment not null,
    cod_mun int not null,
    bairro varchar(30) null,
    rua varchar(30) null,
    casa varchar(15) null,
    telefone int null,
    email varchar(100) null,
    primary key(cod_end),
    foreign key(cod_mun) references tb_municipios(cod_mun));

    /*tabela alunos xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
    create table tb_alunos(
    n_processo int auto_increment not null,
    nome varchar(60) not null,
    data_nasc date not null,
    cod_mun int not null,
    bi varchar(20) not null,
    pai varchar(60) not null,
    mae varchar(60) not null,
    cod_end int not null,
    foto varchar(50) null,
    primary key(n_processo),
    foreign key(cod_mun) references tb_municipios(cod_mun),
    foreign key(cod_end) references tb_enderecos(cod_end));

    /*tabela matriculas xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
    create table tb_matriculas(
    cod_matr int auto_increment not null,
    n_processo int not null,
    cod_curso int not null,
    periodo varchar(15) not null,
    ano_academico varchar(15) not null,
    ano_lectivo varchar(15) not null,
    data_matr date not null,
    primary key(cod_matr),
    foreign key(n_processo) references tb_alunos(n_processo),
    foreign key(cod_curso) references tb_cursos(cod_curso));

  9. Justino Miranda Says:

    query em php

    $inserir_enderecos=mysql_query(“INSERT INTO tb_enderecos (cod_end, cod_mun, bairro, rua, casa, telefone, email) VALUES (null,’$municipio2′,’$bairro’,’$rua’,’$casa’,’$telefone’,’$email’)”);
    $id_inserir_enderecos= mysql_insert_id($inserir_enderecos);
    $inserir_alunos=mysql_query(“INSERT INTO tb_alunos (nome, data_nasc, cod_mun, bi, pai, mae, cod_end foto) VALUES (‘$nome’,’$nacimento’,’$municipio’,’$bi’,’$pai’,’$mae’,’$id_inserir_enderecos’,’$imagem'”);
    $id_inserir_alunos= mysql_insert_id($inserir_alunos);
    $inserir_matriculas=mysql_query(“INSERT INTO tb_matriculas (n_processo, cod_curso, periodo, ano_academico, ano_lectivo, data_matr) VALUES (‘$id_inserir_alunos’,’$curso’,’$periodo’,’$ano_acad’,’$ano_lect’,’$data_matr'”);

  10. Lyxinha Says:

    preciso sabber como pegar id de quatro tabelas e inserir como chave estrageira na outra tabela, tenho esse codigo mas pega apenas um id e coloca nas outras:

    $sql= mysql_query(“INSERT INTO representante (nome_rep,nome_comercial,rua_rep,cp_rep,vila_rep,lugar_rep,zona_rep,ilha_rep,pais_rep) VALUES (‘$representante’,’$nome_cmer_repres’,’$rua_repres’,’$cp_repres’,’$vila_repres’,’$lugar_repres’,’$zona_repres’,’$ilha_repres’,’$pais_repres’)”) or die (mysql_error());

    $sql2= mysql_query(“INSERT INTO entidade_externa (s_externo,nome_entidade,rua_entidade,cp_entidade,cidade_entidade,vila_entidade,lugar_entidade,zona_entidade,ilha_entidade) VALUES (‘$s_externo’,’$nome_entidade’,’$rua_entidade’,’$cp_entidade’,’$cidade_entidade’,’$vila_entidade’,’$lugar_entidade’,’$zona_entidade’,’$ilha_entidade’)”) or die (mysql_error());

    $sql3= mysql_query(“INSERT INTO dados_pessoais (telefone,telefone_fixo,telefone_movel,utilizador_telef,categ_funcao,num_telef_chamado,tipo_chamada,duracao_chamada,custo_comunicacao,correio_electonico,end_destinatario,end_remetente,assunto,data_hora_envio,tipo_ficheiro_anexo,internet,utilizador_net,data_hora_conexao_net) VALUES (‘$value6′,’$value7′,’$value8′,’$value9′,’$value10′,’$value11′,’$value12′,’$value13′,’$value14′,’$value15′,’$value17′,’$value18′,’$value19′,’$value20′,’$value21′,’$value16′,’$value22′,’$value23’)”) or die (mysql_error());

    $sql4= mysql_query(“INSERT INTO direito_acesso (morada_local,rua,caixa_postal,cidade,vila,lugar,zona,ilha,concelho,email,telefone,presencial,escrita,outra) VALUES (‘$value28′,’$rua_dacesso’,’$cp_dacesso’,’$vila_dacesso’,’$lugar_dacesso’,’$cidade_dacesso’,’$zona_dacesso’,’$ilha_dacesso’,’$concelho_dacesso’,’$email_dacesso’,’$telefone_dacesso’,’$value29′,’$value30′,’$outra’)”) or die (mysql_error());

    $id = mysql_insert_id();
    $id2 = mysql_insert_id();
    $id3 = mysql_insert_id();
    $id4 = mysql_insert_id();

    $sql5= mysql_query(“INSERT INTO notificacao_tenet (id_rep,id_est_externa,id_dadospessoais,id_dac,tipo_notificacao,num_processo,ano_processo,tipo_pessoa,denom_nome,nome_comercial,nif,atividade_des,rua,cp,cidade,vila,lugar,zona,ilha,email,pais,pessoa_contato,email_pessoa_cont,telef_pessoa_cont,gestao_empresa,gestao_produt_trab,siglio_jornalista,siglio_prof_saude,siglio_advogados,siglio_minist_culto,representante_trab,medida_seguranca,regulamento_interno,data_notificacao) VALUES (‘$id’,’$id2′,’$id3′,’$id4′, ‘$OPCAO’,’$num_processo’,’$ano_processo’,’$pessoa’,’$denom_nome’,’$nome_comercial’,’$nif’,’$atividade_des’,’$rua’,’$cp’,’$cidade’,’$vila’,’$lugar’,’$zona’,’$ilha’,’$email’,’$pais’,’$pessoa_contato’,’$email_pessoa_cont’,’$telef_pessoa_cont’,’$value4′,’$value5′,’$value24′,’$value25′,’$value26′,’$value27′,’$reptrab’,’$value31′,’$regulint’,Now())”) or die (mysql_error());

  11. Robert Says:

    to com um problema parecido…fiz um formulario onde tem a parte de cabeçalho e a parte detalhe, só que estou com um problema quando clono as linhas e mando inserir no BD ele insere varias vezes e perde o last_insert.

    Alguma luz, por favor.

    mysql_query(“INSERT INTO lc_controle (id,dia, mes, ano, dtConcat, clienteVa, clienteAt, userml, rastreador, entrega, total, frete, frete_real, nf, origem, tipo_pagto, descricao, tipo, tipo_venda) values
    (‘null’,’$dia’, ‘$mes’, ‘$ano’, ‘$dtConcat’, ‘$clienteVa’, ‘0’, ‘$userml’, ‘$rastreador’, ‘$entrega’, ‘$total’, ‘$frete’, ‘$frete_real’, ‘$nf’, ‘$origem’, ‘$tipo_pagto’, ‘$descricao’,’0′,’Varejo’)”);

    foreach($_POST[“cat_id”] as $cat_id)
    foreach($_POST[“qtd”] as $qtd)
    foreach($_POST[“valor_unid”] as $valor_unid)
    foreach($_POST[“valor_total”] as $valor_total)

    mysql_query(“INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id)
    values
    (‘$cat_id’,’$qtd’,’$valor_unid’,’$valor_total’,LAST_INSERT_ID())”);


Deixar mensagem para Thamires de Oliveira Cancelar resposta