web-dev-qa-db-fra.com

@@ IDENTITY, SCOPE_IDENTITY (), OUTPUT et autres méthodes de récupération de la dernière identité

J'ai vu diverses méthodes utilisées lors de la récupération de la valeur d'un champ d'identité de clé primaire après l'insertion.

declare @t table (
    id int identity primary key,
    somecol datetime default getdate()
)
insert into @t
default values

select SCOPE_IDENTITY() --returns 1
select @@IDENTITY --returns 1

Retour d'un tableau d'identités après l'insertion:

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values   

Quelle méthode est appropriée ou meilleure? La méthode OUTPUT est-elle sans danger pour la portée?

Le deuxième extrait de code a été emprunté à SQL in the Wild

57
Seibar

Cela dépend de ce que vous essayez de faire ...

@@IDENTITÉ

Renvoie la dernière valeur IDENTITY produite sur une connexion, quelle que soit la table qui a produit la valeur et quelle que soit la portée de l'instruction qui a produit la valeur. @@ IDENTITY renverra la dernière valeur d'identité entrée dans un tableau de votre session en cours. @@ IDENTITY est limité à la session en cours et n'est pas limité à la portée actuelle. Par exemple, si vous avez un déclencheur sur une table qui provoque la création d'une identité dans une autre table, vous obtiendrez l'identité qui a été créée en dernier, même si c'est le déclencheur qui l'a créée.

SCOPE_IDENTITY ()

Renvoie la dernière valeur IDENTITY produite sur une connexion et par une instruction dans la même étendue, quelle que soit la table qui a produit la valeur. SCOPE_IDENTITY () est similaire à @@ IDENTITY, mais il limitera également la valeur à votre étendue actuelle. En d'autres termes, il renverra la dernière valeur d'identité que vous avez créée explicitement, plutôt que toute identité créée par un déclencheur ou une fonction définie par l'utilisateur.

IDENT_CURRENT ()

Renvoie la dernière valeur IDENTITY produite dans une table, indépendamment de la connexion et de la portée de l'instruction qui a produit la valeur. IDENT_CURRENT est limité à une table spécifiée, mais pas par connexion ou étendue.

72
mson

Notez qu'il y a un bogue dans scope_identity() et @@identity - voir MS Connect: https://connect.Microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=328811

Un devis (de Microsoft):

Je recommande fortement d'utiliser OUTPUT au lieu de @@IDENTITY dans tous les cas. C'est juste la meilleure façon de lire l'identité et l'horodatage.

Modifié pour ajouter: cela peut être corrigé maintenant. Connect me donne une erreur, mais voyez:

Scope_Identity () renvoyant une valeur incorrecte fixée?

12
Simon D

Il n'y a presque aucune raison d'utiliser autre chose qu'une clause OUTPUT lorsque vous essayez d'obtenir l'identité des lignes qui viennent d'être insérées. La clause OUTPUT est étendue et sécurisée pour les tables.

Voici un exemple simple pour obtenir l'ID après avoir inséré une seule ligne ...

DECLARE @Inserted AS TABLE (MyTableId INT);

INSERT [MyTable] (MyTableColOne, MyTableColTwo)
OUTPUT Inserted.MyTableId INTO @Inserted
VALUES ('Val1','Val2')

SELECT MyTableId FROM @Inserted

Documents détaillés pour la clause OUTPUT: http://technet.Microsoft.com/en-us/library/ms177564.aspx


-- table structure for example:     
CREATE TABLE MyTable (
    MyTableId int NOT NULL IDENTITY (1, 1),
    MyTableColOne varchar(50) NOT NULL,
    MyTableColTwo varchar(50) NOT NULL
)
8
JeremyWeir

@@ L'identité est à l'ancienne. Utilisez SCOPE_IDENTITY () dans tous les cas à l'avenir. Voir MSDN pour les répercussions de l'utilisation de @@ IDENTITY (ils sont mauvais!).

6
jcollum

SCOPE_IDENTITY est suffisant pour des lignes simples et est recommandé sauf dans les cas où vous devez voir le résultat d'un TRIGGER intermédiaire pour une raison quelconque (pourquoi?).

Pour plusieurs lignes, OUTPUT/OUTPUT INTO est votre nouveau meilleur ami et alternative pour retrouver les lignes et les insérer dans une autre table.

4
Cade Roux

Il existe une autre méthode disponible dans SQL Server 2005 qui est décrite dans SQL à l'état sauvage .

Cela vous permettra de récupérer plusieurs identités après l'insertion. Voici le code du blog:

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values
3
Seibar

Une petite correction à la réponse de Godeke:

Ce n'est pas seulement les déclencheurs dont vous devez vous soucier. Tout type d'opération imbriquée, comme les procs stockés, qui entraîne la création d'identificateurs peut modifier la valeur de @@ IDENTITY.

Un autre vote pour scope_identity ...

3
Paul Sasik

Soyez prudent lorsque vous utilisez @@ IDENTITY ...

http://dotnetgalactics.wordpress.com/2009/10/28/scope-identity-vs-identity/

1
Pato