Je sais que Scope_Identity()
, Identity()
, @@Identity
Et Ident_Current()
obtiennent tous la valeur de la colonne identité, mais j'aimerais connaître la différence. .
Une partie de la controverse que j'ai est de savoir ce qu'ils entendent par portée appliqué à ces fonctions ci-dessus.
J'aimerais aussi un exemple simple de différents scénarios d'utilisation?
@@identity
Renvoie la dernière identité créée dans la même session.scope_identity()
renvoie la dernière identité créée dans la même session et la même étendue.ident_current(name)
renvoie la dernière identité créée pour une table ou une vue spécifique dans une session.identity()
n'est pas utilisée pour obtenir une identité, mais pour créer une identité dans une requête select...into
.La session est la connexion à la base de données. L'étendue est la requête en cours ou la procédure stockée en cours.
Une situation dans laquelle scope_identity()
et @@identity
Diffèrent est si vous avez un déclencheur sur la table. Si vous avez une requête qui insère un enregistrement, le déclencheur insérant un autre enregistrement quelque part, la fonction scope_identity()
retournera l'identité créée par la requête, tandis que la fonction @@identity
Renverra l'identité créé par le déclencheur.
Donc, normalement, vous utiliseriez la fonction scope_identity()
.
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 voudrez, mais parfois ce ne sera pas le cas (comme lorsqu'un déclencheur est déclenché en réponse à un INSERT
et qu'il exécute une autre instruction INSERT
.).
SCOPE_IDENTITY()
: renvoie la dernière valeur d'identité générée dans l'étendue actuelle (c'est-à-dire la procédure stockée, le déclencheur, la fonction, etc.).
IDENT_CURRENT()
: renvoie la dernière valeur d'identité pour une table spécifique. N'utilisez pas ceci 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 en tant que colonne d'identité.
Pour plus de références, voir: http://msdn.Microsoft.com/en-us/library/ms187342.aspx .
Pour résumer: si vous insérez des lignes et que vous voulez connaître la valeur de la colonne identité pour la ligne vous que vous venez d'insérer, utilisez toujours SCOPE_IDENTITY()
.
Si vous comprenez la différence entre scope et session, il sera très facile de comprendre ces méthodes.
Un très gentil article de blog par Adam Anderson décrit cette différence:
Session désigne la connexion en cours qui exécute la commande.
Portée désigne le contexte immédiat d'une commande. Chaque appel de procédure stockée s'exécute dans sa propre étendue et les appels imbriqués s'exécutent dans une étendue imbriquée dans l'étendue de la procédure d'appel. De même, une commande SQL exécutée à partir d'une application ou de SSMS s'exécute dans sa propre portée. Si cette commande déclenche un déclencheur, chaque déclencheur s'exécute dans sa propre portée imbriquée.
Ainsi, les différences entre les trois méthodes de récupération d'identité sont les suivantes:
@@identity
Renvoie la dernière valeur d'identité générée dans this session mais any portée.
scope_identity()
renvoie la dernière valeur d'identité générée dans this session et this portée.
ident_current()
renvoie la dernière valeur d'identité générée pour une table particulière dans any session et any scope.
Scope désigne le contexte de code qui exécute l'instruction INSERT
, SCOPE_IDENTITY()
, par opposition à l'étendue 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.
En raison du bogue mentionné par @David Freitas et de l'incompatibilité de la nouvelle fonctionnalité Séquence introduite en 2012, je vous conseillerais de ne pas vous y intéresser. Au lieu de cela, vous pouvez utiliser la clause OUTPUT pour obtenir la valeur d'identité insérée. L’autre avantage est que OUTPUT fonctionne même si vous avez inséré plus d’une ligne.
Pour plus de détails et des exemples, voir ici: Crise d'identité
Pour clarifier le problème avec @@Identity
:
Par exemple, si vous insérez une table et que cette dernière a des déclencheurs effectuant des insertions, @@Identity
Renverra l'identifiant de l'insertion dans le déclencheur (un log_id
Ou quelque chose d'autre), tandis que scope_identity()
retournera l'id de l'insertion dans la table d'origine.
Donc, si vous n'avez pas de déclencheurs, scope_identity()
et @@identity
Renverront la même valeur. Si vous avez des déclencheurs, vous devez réfléchir à la valeur que vous souhaitez.
Voici une autre bonne explication de le livre :
En ce qui concerne 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é
- Appel à une procédure stockée P2 qui comporte également une instruction INSERT qui génère une nouvelle 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 portée). La fonction @@ IDENTITY renverra la valeur générée par P2 (même session quelle que soit la portée).
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 résultant 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 renverra l'identité de l'enregistrement inséré à partir du déclencheur.
IdentCurrent
: La dernière identité attribuée à la table.