Pergunta

Qual é a melhor forma de conseguir IDENTITY da linha inserida?

Eu sei sobre @@IDENTITY e IDENT_CURRENT e SCOPE_IDENTITY mas não entendo os prós e os contras de cada um.

Alguém pode explicar as diferenças e quando devo usar cada uma?

Foi útil?

Solução

  • @@IDENTITY retorna o último valor de identidade gerado para qualquer tabela na sessão atual, em todos os escopos. Você precisa ter cuidado aqui, já que está entre escopos.Você poderia obter um valor de um gatilho, em vez de sua instrução atual.

  • SCOPE_IDENTITY() retorna o último valor de identidade gerado para qualquer tabela na sessão atual e no escopo atual. Geralmente o que você deseja usar.

  • IDENT_CURRENT('tableName') retorna o último valor de identidade gerado para uma tabela específica em qualquer sessão e em qualquer escopo.Isso permite especificar de qual tabela você deseja o valor, caso as duas acima não sejam exatamente o que você precisa (muito raro).Tambem como @Cara Starbuck mencionado, "Você pode usar isso se quiser obter o valor IDENTITY atual para uma tabela na qual não inseriu um registro."

  • O OUTPUT cláusula do INSERT instrução permitirá que você acesse todas as linhas inseridas por meio dessa instrução.Como tem como escopo a instrução específica, é mais direto do que as outras funções acima.Porém, é um pouco mais detalhado (você precisará inserir em uma tabela variável/temperária e depois consultá-la) e fornece resultados mesmo em um cenário de erro em que a instrução é revertida.Dito isto, se a sua consulta usa um plano de execução paralelo, este é o único método garantido para obter a identidade (exceto desligar o paralelismo).No entanto, é executado antes gatilhos e não pode ser usado para retornar valores gerados por gatilhos.

Outras dicas

Acredito que o método mais seguro e preciso de recuperar o ID inserido seria usando a cláusula de saída.

por exemplo (retirado do seguinte MSDN artigo)

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate 
FROM Production.ScrapReason;
GO

Estou dizendo a mesma coisa que os outros caras, então todos estão corretos, só estou tentando deixar isso mais claro.

@@IDENTITY retorna o id da última coisa que foi inserida pela conexão do seu cliente com o banco de dados.
Na maioria das vezes isso funciona bem, mas às vezes um gatilho irá inserir uma nova linha que você não conhece, e você obterá o ID dessa nova linha, em vez daquela que deseja

SCOPE_IDENTITY() resolve esse problema.Ele retorna o id da última coisa que você inseriu no código SQL você enviou para o banco de dados.Se os gatilhos criarem linhas extras, eles não farão com que o valor errado seja retornado.Viva

IDENT_CURRENT retorna o último ID inserido por alguém.Se algum outro aplicativo inserir outra linha em um momento infeliz, você obterá o ID dessa linha em vez do seu.

Se você quiser jogar pelo seguro, sempre use SCOPE_IDENTITY().Se você ficar com @@IDENTITY e alguém decidir adicionar um gatilho mais tarde, todo o seu código será quebrado.

O melhor (leia:A maneira mais segura) de obter a identidade de uma linha recém-inserida é usando o output cláusula:

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)

Adicionar

SELECT CAST(scope_identity() AS int);

ao final da sua instrução insert sql, então

NewId = command.ExecuteScalar()

irá recuperá-lo.

MSDN

@@IDENTITY, SCOPE_IDENTITY e IDENT_CURRENT são funções semelhantes porque retornam o último valor inserido na coluna IDENTITY de uma tabela.

@@IDENTITY e SCOPE_IDENTITY retornarão o último valor de identidade gerado em qualquer tabela da sessão atual.Entretanto, SCOPE_IDENTITY retorna o valor apenas dentro do escopo atual;@@IDENTITY não está limitado a um escopo específico.

IDENT_CURRENT não é limitado por escopo e sessão;está limitado a uma tabela especificada.IDENT_CURRENT retorna o valor de identidade gerado para uma tabela específica em qualquer sessão e em qualquer escopo.Para obter mais informações, consulte IDENT_CURRENT.

  • IDENT_CURRENT é uma função que recebe uma tabela como argumento.
  • @@IDENTIDADE pode retornar resultados confusos quando você tem um gatilho na mesa
  • SCOPE_IDENTITY é seu herói na maioria das vezes.

Quando você usa o Entity Framework, ele usa internamente o OUTPUT técnica para retornar o valor do ID recém-inserido

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');

SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g 
   JOIN dbo.TurboEncabulators AS t 
   ON g.Id = t.TurboEncabulatorID 
WHERE @@ROWCOUNT > 0

Os resultados de saída são armazenados em uma variável de tabela temporária, unidos novamente à tabela e retornam o valor da linha fora da tabela.

Observação:Não tenho ideia de por que a EF uniria internamente a tabela efêmera de volta à tabela real (sob quais circunstâncias as duas não corresponderiam).

Mas é isso que a EF faz.

Esta técnica (OUTPUT) está disponível apenas no SQL Server 2008 ou mais recente.

@@IDENTIDADE é a última identidade inserida usando a conexão SQL atual.Este é um bom valor para retornar de um procedimento armazenado de inserção, onde você só precisa da identidade inserida para seu novo registro e não se importa se mais linhas forem adicionadas posteriormente.

SCOPE_IDENTITY é a última identidade inserida usando a Conexão SQL atual, e no escopo atual - ou seja, se houvesse uma segunda IDENTITY inserida com base em um trigger após sua inserção, ela não seria refletida em SCOPE_IDENTITY, apenas a inserção que você realizou.Francamente, nunca tive um motivo para usar isso.

IDENT_CURRENT(nome da tabela) é a última identidade inserida independentemente da conexão ou do escopo.Você pode usar isso se quiser obter o valor IDENTITY atual para uma tabela na qual não inseriu um registro.

Não posso falar com outras versões do SQL Server, mas em 2012, a saída direta funciona perfeitamente.Você não precisa se preocupar com uma mesa temporária.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

A propósito, essa técnica também funciona ao inserir várias linhas.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

Saída

ID
2
3
4

SEMPRE use scope_identity(), NUNCA há necessidade de mais nada.

Após sua instrução de inserção, você precisa adicionar isso.E certifique-se do nome da tabela onde os dados estão sendo inseridos. Você obterá a linha atual e não a linha afetada agora pela sua instrução de inserção.

IDENT_CURRENT('tableName')

Se você está procurando o último ID adicionado/atualizado, isso pode ser um pouco antiquado, mas há muitas pessoas usando PHP mais antigo, Pré 5.5 para ser mais preciso.Mais detalhes podem ser encontrados em http://php.net/manual/en/function.mysql-insert-id.php

$last = mysql_insert_id();

Criar uma uuid e também insira-o em uma coluna.Então você pode identificar facilmente sua linha com o uuid.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top