sql - value - Melhor maneira de obter identidade da linha inserida?




sql server management studio modify column (8)

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

por exemplo (retirado do seguinte artigo do MSDN )

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

Qual é a melhor maneira de obter a IDENTITY da linha inserida?

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

Alguém por favor pode explicar as diferenças e quando eu deveria estar usando cada um?


Adicionar

SELECT CAST(scope_identity() AS int);

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

NewId = command.ExecuteScalar()

irá recuperá-lo.


Eu estou dizendo a mesma coisa que os outros caras, então todo mundo está correto, eu estou apenas tentando deixar isso mais claro.

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

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

IDENT_CURRENT retorna o último ID que foi inserido por qualquer pessoa. Se algum outro aplicativo inserir outra linha em um horário não desejado, você receberá o ID dessa linha em vez da sua.

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


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

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

By the way, esta técnica também funciona ao inserir várias linhas.

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

Saída

ID
2
3
4

Quando você usa o Entity Framework, ele usa internamente a técnica OUTPUT para retornar o valor de 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 de volta à tabela e retornam o valor da linha para fora da tabela.

Nota: Eu não tenho idéia de por que o EF iria se juntar à mesa efêmera de volta à mesa real (sob quais circunstâncias os dois não combinariam).

Mas é o que a EF faz.

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


MSDN

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

@@ IDENTITY e SCOPE_IDENTITY retornarão o último valor de identidade gerado em qualquer tabela na sessão atual. No entanto, SCOPE_IDENTITY retorna o valor somente dentro do escopo atual; @@ IDENTIDADE não está limitada a um escopo específico.

IDENT_CURRENT não está 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 qualquer escopo. Para mais informações, consulte IDENT_CURRENT.

  • IDENT_CURRENT é uma função que aceita uma tabela como argumento.
  • MSDN pode retornar resultado confuso quando você tem um gatilho na mesa
  • SCOPE_IDENTITY é seu herói a maior parte do tempo.

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


  • @@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á nos escopos. Você poderia obter um valor de um gatilho, em vez de sua declaraçã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 qualquer escopo. Isso permite que você especifique de qual tabela você quer o valor, caso os dois acima não sejam exatamente o que você precisa ( muito raro ). Além disso, como @ Guy Starbuck mencionou: "Você poderia usar isso se quiser obter o valor IDENTITY atual para uma tabela na qual você não inseriu um registro."

  • A cláusula OUTPUT da instrução INSERT permitirá que você acesse todas as linhas inseridas por meio dessa instrução. Desde o escopo da declaração específica, é mais simples do que as outras funções acima. No entanto, ele é um pouco mais detalhado (você precisará inserir uma tabela / tabela temporária e, em seguida, consultá-la) e fornecerá resultados mesmo em um cenário de erro em que a instrução será revertida. Dito isso, se sua consulta usa um plano de execução paralela, esse é o único método garantido para obter a identidade (além de desativar o paralelismo). No entanto, ele é executado antes dos acionadores e não pode ser usado para retornar valores gerados pelo acionador.







tsql