Qual é a diferença entre Scope_Identity (), Identity (), @@ Identity e Ident_Current ()?

191

Eu sei Scope_Identity(), Identity(),@@Identity, and Ident_Current() all get the value of the identity column, but I would love to know the difference.

Part of the controversy I'm having is what do they mean by scope as applied to these functions above?

Eu também adoraria um exemplo simples de diferentes cenários de usá-los?

Tebo
fonte
2
Don't forget about the parallel execution bug that exists in SQL Server for SCOPE_IDENTITY and @@IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas
@DaviddCeFreitas -- I'm curious to read about the bug, but the link appears to be broken (or at least, it's throwing an ASP error).
rory.ap
2
Actually, I found it: support.microsoft.com/en-us/kb/2019779
rory.ap
Fix had been released as mentioned at that old KB article
George Birbilis

Respostas:

392
  • The @@identity function returns the last identity created in the same session.
  • The scope_identity() function returns the last identity created in the same session and the same scope.
  • The ident_current(name) returns the last identity created for a specific table or view in any session.
  • The identity() function is not used to get an identity, it's used to create an identity in a select...into query.

The session is the database connection. The scope is the current query or the current stored procedure.

A situation where the scope_identity() and the @@identity functions differ, is if you have a trigger on the table. If you have a query that inserts a record, causing the trigger to insert another record somewhere, the scope_identity() function will return the identity created by the query, while the @@identity function will return the identity created by the trigger.

So, normally you would use the scope_identity() function.

Guffa
fonte
14
Eu escolhi isso como a resposta, devido ao parágrafo "Uma situação em que o scope_identity () e o @@ identity ...". Esclareceu mais as coisas.
Tebo
1
Como David Freitas mencionou acima, há um erro na implementação do scope_identity, por isso recomendo usar um método alternativo, a cláusula OUTPUT. Veja minha resposta abaixo.
Sebastian Meine
@ Guffa - "A sessão é a conexão com o banco de dados". A sessão é mantida nas conexões se você estiver usando o Pool de Conexões?
Dave Black
1
Esta é uma resposta de modelo. Em particular, trabalhar com SQL e SQL Server pode ser estranho, e isso explica as coisas de uma maneira muito clara e leiga, enquanto ainda é bastante informativo. Não parece algo sendo comunicado entre dois especialistas em banco de dados, o que muitas outras respostas do SE fazem.
Panzercrisis
@DaveBlack pelo que li: Não, a sessão não é mantida no pool, a sessão é exclusiva para a execução do script após o connect (). Ao agrupar ... O PHP for SQL Server usa o conjunto de conexões ODBC. Quando uma conexão do pool é usada, o estado da conexão é redefinido. Fechar a conexão retorna a conexão ao pool. (note: veja comentários para linux / mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

Boa pergunta.

  • @@IDENTITY: retorna o último valor de identidade gerado na sua conexão SQL (SPID). Na maioria das vezes, será o que você deseja, mas às vezes não é (como quando um gatilho é disparado em resposta a um INSERTe o gatilho executa outra INSERTinstrução).

  • SCOPE_IDENTITY(): retorna o último valor de identidade gerado no escopo atual (ou seja, procedimento armazenado, gatilho, função etc.).

  • IDENT_CURRENT(): retorna o último valor de identidade para uma tabela específica. Não use isso para obter o valor da identidade de umINSERT , pois está sujeito a condições de corrida (ou seja, várias conexões inserindo linhas na mesma tabela).

  • IDENTITY(): usado ao declarar uma coluna em uma tabela como uma coluna de identidade.

Para mais referência, consulte: http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Para resumir: se você estiver inserindo linhas e quiser saber o valor da coluna de identidade da linha que você acabou de inserir, use sempre SCOPE_IDENTITY().

Brannon
fonte
16

Se você entender a diferença entre escopo e sessão, será muito fácil entender esses métodos.

Um post muito bom de Adam Anderson descreve esta diferença:

Sessão significa a conexão atual que está executando o comando.

Escopo significa o contexto imediato de um comando. Toda chamada de procedimento armazenado é executada em seu próprio escopo e as chamadas aninhadas são executadas em um escopo aninhado no escopo do procedimento de chamada. Da mesma forma, um comando SQL executado a partir de um aplicativo ou SSMS é executado em seu próprio escopo e, se esse comando disparar qualquer gatilho, cada gatilho será executado dentro de seu próprio escopo aninhado.

Portanto, as diferenças entre os três métodos de recuperação de identidade são as seguintes:

@@identityretorna o último valor de identidade gerado nesta sessão, mas qualquer escopo.

scope_identity()retorna o último valor de identidade gerado nesta sessão e neste escopo.

ident_current()retorna o último valor de identidade gerado para uma tabela específica em qualquer sessão e qualquer escopo.

Hemant Sakta
fonte
11

Escopo significa o contexto do código que executa a INSERTinstrução SCOPE_IDENTITY(), em oposição ao escopo global de @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Dá resultados diferentes.

devio
fonte
9

Por causa do bug mencionado por @David Freitas e por causa da incompatibilidade com o novo recurso Sequence que foi introduzido em 2012, eu recomendaria ficar longe desses três. Em vez disso, você pode usar a cláusula OUTPUT para obter o valor da identidade inserido. A outra vantagem é que OUTPUT funciona mesmo se você tiver inserido mais de uma linha.

Para detalhes e exemplos, consulte aqui: Crise de identidade

Sebastian Meine
fonte
Eu acho que essa resposta merece mais atenção.
CHEEZE
Infelizmente, INSERT ... OUTPUT Inserted.xx não funciona com gatilhos INSERT (o mesmo vale para gatilhos UPDATE ... OUTPUT Updated.xx e UPDATE). Eles sugerem o uso de INSERT ... OUTPUT INTO, mas é muito detalhado e o uso de clientes (em vez de procs armazenados) é problemático. INSERIR ... SAÍDA Inserted.xx é bonito quando usado com chamadas do lado do cliente (você só precisa de um ExecuteScalar para inserir e dizer recuperar o ID gerado automaticamente para a nova linha) se você não precisar dos gatilhos.
George Birbilis
6

Para esclarecer o problema com @@Identity :

Por exemplo, se você inserir uma tabela e essa tabela tiver gatilhos fazendo inserções, @@Identityretornará o ID da inserção no gatilho (a log_idou algo assim), enquantoscope_identity() retornará o ID da inserção na tabela original.

Então, se você não tem nenhum gatilhos, scope_identity()e @@identityirá retornar o mesmo valor. Se você tiver gatilhos, precisará pensar em qual valor gostaria.

Jonas Lincoln
fonte
4

Scope Identity: Identidade do último registro adicionado ao procedimento armazenado que está sendo executado.

@@Identity: Identity of last record added within the query batch, or as a result of the query e.g. a procedure that performs an insert, the then fires a trigger that then inserts a record will return the identity of the inserted record from the trigger.

IdentCurrent: The last identity allocated for the table.

Andrew
fonte
3

Here is another good explanation from the book:

As for the difference between SCOPE_IDENTITY and @@IDENTITY, suppose that you have a stored procedure P1 with three statements:
- An INSERT that generates a new identity value
- A call to a stored procedure P2 that also has an INSERT statement that generates a new identity value
- A statement that queries the functions SCOPE_IDENTITY and @@IDENTITY The SCOPE_IDENTITY function will return the value generated by P1 (same session and scope). The @@IDENTITY function will return the value generated by P2 (same session irrespective of scope).

Dmitriy Dokshin
fonte