AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 124847
Accepted
AA.SC
AA.SC
Asked: 2015-12-31 05:08:11 +0800 CST2015-12-31 05:08:11 +0800 CST 2015-12-31 05:08:11 +0800 CST

Melhor maneira de obter a última identidade inserida em uma tabela

  • 772

Qual é a melhor opção para obter o valor de identidade que acabei de gerar por meio de uma inserção? Qual é o impacto dessas declarações em termos de desempenho?

  1. SCOPE_IDENTITY()
  2. Função agregadaMAX()
  3. SELECT TOP 1IdentityColumn FROM TableNameORDER BY IdentityColumn DESC
sql-server sql-server-2008-r2
  • 2 2 respostas
  • 246327 Views

2 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2015-12-31T06:49:55+08:002015-12-31T06:49:55+08:00

    UseSCOPE_IDENTITY() se estiver inserindo uma única linha e quiser recuperar o ID que foi gerado.

    CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));
    
    INSERT #a(x) VALUES('a');
    
    SELECT SCOPE_IDENTITY();
    

    Resultado:

    ----
    1
    

    Use a OUTPUTcláusula se estiver inserindo várias linhas e precisar recuperar o conjunto de IDs que foram gerados.

    INSERT #a(x) 
      OUTPUT inserted.identity_column 
      VALUES('b'),('c');
    

    Resultado:

    ----
    2
    3
    

    e por que esta é a melhor opção mais rápida?

    Além do desempenho, esses são os únicos que garantem estar corretos no nível de isolamento padrão e/ou com vários usuários. Mesmo se você ignorar o aspecto de correção, o SQL Server mantém o valor inserido SCOPE_IDENTITY()na memória, portanto, naturalmente, isso será mais rápido do que executar sua própria consulta isolada na tabela ou nas tabelas do sistema.

    Ignorar o aspecto de correção é como dizer ao carteiro que ele fez um bom trabalho entregando a correspondência de hoje - ele terminou sua rota 10 minutos mais rápido que seu tempo médio, o problema é que nenhuma correspondência foi entregue na casa certa.

    Não use nenhum dos seguintes:

    • @@IDENTITY- como isso não pode ser usado em todos os cenários, por exemplo, quando uma tabela com uma coluna de identidade tem um gatilho que também insere em outra tabela com sua própria coluna de identidade - você receberá o valor errado de volta.
    • IDENT_CURRENT()- Eu entro em detalhes sobre isso aqui , e os comentários são uma leitura útil também, mas essencialmente, em concorrência, você muitas vezes receberá a resposta errada.
    • MAX()ou TOP 1- você teria que proteger as duas instruções com isolamento serializável para garantir que o que MAX()você obtém não seja de outra pessoa. Isso é muito mais caro do que apenas usar SCOPE_IDENTITY().

    Essas funções também falham sempre que você insere duas ou mais linhas, e precisa de todos os valores de identidade gerados - sua única opção aí é a OUTPUTcláusula.

    • 67
  2. db2
    2015-12-31T06:09:44+08:002015-12-31T06:09:44+08:00

    Além do desempenho, todos eles têm significados bastante diferentes.

    SCOPE_IDENTITY()fornecerá o último valor de identidade inserido em qualquer tabela diretamente no escopo atual (escopo = lote, procedimento armazenado etc., mas não dentro, digamos, de um gatilho que foi disparado pelo escopo atual).

    IDENT_CURRENT()fornecerá o último valor de identidade inserido em uma tabela específica de qualquer escopo, por qualquer usuário.

    @@IDENTITYfornece o último valor de identidade gerado pela instrução INSERT mais recente para a conexão atual, independentemente da tabela ou do escopo. (Observação: o Access usa essa função e, portanto, tem alguns problemas com gatilhos que inserem valores em tabelas com colunas de identidade.)

    Usar MAX()ou TOP 1pode fornecer resultados totalmente errados se a tabela tiver uma etapa de identidade negativa ou tiver linhas inseridas SET IDENTITY_INSERTem jogo. Aqui está um script demonstrando tudo isso:

    CREATE TABLE ReverseIdent (
        id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
        data char(4)
    )
    
    INSERT INTO ReverseIdent (data)
    VALUES ('a'), ('b'), ('c')
    
    SELECT * FROM ReverseIdent
    
    SELECT IDENT_CURRENT('ReverseIdent') --8998
    SELECT MAX(id) FROM ReverseIdent --9000
    
    SET IDENTITY_INSERT ReverseIdent ON
    
    INSERT INTO ReverseIdent (id, data)
    VALUES (9005, 'd')
    
    SET IDENTITY_INSERT ReverseIdent OFF
    
    SELECT IDENT_CURRENT('ReverseIdent') --8998
    SELECT MAX(id) FROM ReverseIdent --9005
    

    Resumo: fique com SCOPE_IDENTITY(), IDENT_CURRENT(), ou @@IDENTITY, e certifique-se de estar usando aquele que retorna o que você realmente precisa.

    • 10

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve