Quelle est la différence entre Scope_Identity (), Identity (), @@ Identity et Ident_Current ()?

192

Je sais que Scope_Identity(), Identity(), @@Identityet Ident_Current()tous obtenir la valeur de la colonne d'identité, mais j'aimerais connaître la différence.

Une partie de la controverse que j'ai est que signifient-ils par la portée appliquée à ces fonctions ci-dessus?

J'aimerais aussi un exemple simple de différents scénarios d'utilisation?

Tebo
la source
2
N'oubliez pas le bogue d'exécution parallèle qui existe dans SQL Server pour SCOPE_IDENTITY et @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas
@DaviddCeFreitas - Je suis curieux de lire sur le bogue, mais le lien semble être rompu (ou du moins, il lance une erreur ASP).
rory.ap
2
En fait, je l'ai trouvé: support.microsoft.com/en-us/kb/2019779
rory.ap
Le correctif avait été publié comme mentionné dans cet ancien article de la base de
connaissances

Réponses:

396
  • La @@identityfonction renvoie la dernière identité créée dans la même session.
  • La scope_identity()fonction renvoie la dernière identité créée dans la même session et la même portée.
  • Le ident_current(name)renvoie la dernière identité créée pour une table ou vue spécifique dans une session.
  • La identity()fonction n'est pas utilisée pour obtenir une identité, elle sert à créer une identité dans une select...intorequête.

La session est la connexion à la base de données. L'étendue est la requête actuelle ou la procédure stockée actuelle.

Une situation où les fonctions scope_identity()et les @@identityfonctions diffèrent, est si vous avez un déclencheur sur la table. Si vous avez une requête qui insère un enregistrement, amenant le déclencheur à insérer un autre enregistrement quelque part, la scope_identity()fonction renverra l'identité créée par la requête, tandis que la @@identityfonction renverra l'identité créée par le déclencheur.

Donc, normalement, vous utiliseriez la scope_identity()fonction.

Guffa
la source
14
J'ai choisi ceci comme réponse, à cause du paragraphe "Une situation où le scope_identity () et le @@ identity ...". Cela clarifiait davantage les choses.
Tebo
1
Comme David Freitas l'a mentionné ci-dessus, il y a un bogue dans l'implémentation de scope_identity, donc je recommande d'utiliser une méthode alternative, la clause OUTPUT. Voir ma réponse ci-dessous.
Sebastian Meine
@Guffa - "La session est la connexion à la base de données". La session est-elle maintenue entre les connexions si vous utilisez le regroupement de connexions?
Dave Black
1
Ceci est une réponse modèle. En particulier, travailler avec SQL et SQL Server peut être étrange, ce qui explique les choses d'une manière très claire et profane, tout en étant assez informatif. Cela ne ressemble pas à quelque chose qui a été communiqué entre deux spécialistes de la base de données, ce que font BEAUCOUP d'autres réponses SE.
Panzercrisis
@DaveBlack d'après ce que j'ai lu: Non, la session n'est pas maintenue dans la piscine, la session est unique pour votre script exécuté après connect (). Lors du pooling ... PHP pour SQL Server utilise le pool de connexions ODBC. Lorsqu'une connexion du pool est utilisée, l'état de la connexion est réinitialisé. La fermeture de la connexion renvoie la connexion au pool. (note: voir les remarques pour linux / mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

Bonne question.

  • @@IDENTITY: renvoie la dernière valeur d'identité générée sur votre connexion SQL (SPID). La plupart du temps, ce sera ce que vous voulez, mais parfois ce n'est pas le cas (comme lorsqu'un déclencheur est déclenché en réponse à un INSERT, et que le déclencheur exécute une autre INSERTinstruction).

  • SCOPE_IDENTITY(): renvoie la dernière valeur d'identité générée dans la portée actuelle (c.-à-d. procédure stockée, déclencheur, fonction, etc.).

  • IDENT_CURRENT(): renvoie la dernière valeur d'identité pour une table spécifique. Ne l'utilisez pas pour obtenir la valeur d'identité d'un INSERT, elle est soumise à des conditions de concurrence (c'est-à-dire plusieurs connexions insérant des lignes sur la même table).

  • IDENTITY(): utilisé lors de la déclaration d'une colonne dans une table comme colonne d'identité.

Pour plus d'informations, voir: http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Pour résumer: si vous insérez des lignes et que vous souhaitez connaître la valeur de la colonne d'identité pour la ligne que vous venez d'insérer, utilisez toujours SCOPE_IDENTITY().

Brannon
la source
16

Si vous comprenez la différence entre la portée et la session, il sera très facile de comprendre ces méthodes.

Un très bel article de blog d'Adam Anderson décrit cette différence:

Session signifie la connexion actuelle qui exécute la commande.

Portée signifie le contexte immédiat d'une commande. Chaque appel de procédure stockée s'exécute dans sa propre portée, et les appels imbriqués s'exécutent dans une portée imbriquée dans la portée de la procédure appelante. De même, une commande SQL exécutée à partir d'une application ou d'un SSMS s'exécute dans sa propre portée, et si cette commande déclenche des déclencheurs, chaque déclencheur s'exécute dans sa propre portée imbriquée.

Ainsi, les différences entre les trois méthodes de recherche d'identité sont les suivantes:

@@identityrenvoie la dernière valeur d'identité générée dans cette session mais n'importe quelle portée.

scope_identity()renvoie la dernière valeur d'identité générée dans cette session et cette étendue.

ident_current()renvoie la dernière valeur d'identité générée pour une table particulière dans n'importe quelle session et n'importe quelle portée.

Hemant Sakta
la source
11

Scope désigne le contexte de code qui exécute l' INSERTinstruction SCOPE_IDENTITY(), par opposition à la portée globale 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 

Donne des résultats différents.

devio
la source
6

Pour clarifier le problème avec @@Identity:

Par exemple, si vous insérez une table et que cette table a des déclencheurs faisant des insertions, @@Identityretournera l'id de l'insertion dans le déclencheur (a log_idou quelque chose), tandis que scope_identity()retournera l'id de l'insertion dans la table d'origine.

Donc, si vous n'avez aucun déclencheur, scope_identity()et @@identityque vous retournerez la même valeur. Si vous avez des déclencheurs, vous devez réfléchir à la valeur que vous souhaitez.

Jonas Lincoln
la source
4

Scope Identity: Identité du dernier enregistrement ajouté dans la procédure stockée en cours d'exécution.

@@Identity: Identité du dernier enregistrement ajouté dans le lot de requêtes, ou à la suite de la requête, par exemple une procédure qui effectue une insertion, puis déclenche un déclencheur qui insère ensuite un enregistrement retournera l'identité de l'enregistrement inséré à partir du déclencheur.

IdentCurrent: La dernière identité allouée pour la table.

Andrew
la source
3

Voici une autre bonne explication du livre :

Quant à la différence entre SCOPE_IDENTITY et @@ IDENTITY, supposons que vous ayez une procédure stockée P1 avec trois instructions:
- Un INSERT qui génère une nouvelle valeur d'identité
- Un appel à une procédure stockée P2 qui a également une instruction INSERT qui génère un nouveau valeur d'identité
- Une instruction qui interroge les fonctions SCOPE_IDENTITY et @@ IDENTITY La fonction SCOPE_IDENTITY renverra la valeur générée par P1 (même session et même étendue). La fonction @@ IDENTITY renverra la valeur générée par P2 (même session quelle que soit la portée).

Dmitriy Dokshin
la source