Question Le meilleur moyen d'obtenir l'identité de la ligne insérée?


Quel est le meilleur moyen d'obtenir IDENTITY de la ligne insérée?

Je sais à propos de @@IDENTITY et IDENT_CURRENT et SCOPE_IDENTITY mais ne comprends pas les avantages et les inconvénients attachés à chacun.

Quelqu'un peut-il expliquer s'il vous plaît les différences et quand je devrais utiliser chacun?


889
2017-09-03 21:32


origine


Réponses:


  • @@IDENTITY renvoie la dernière valeur d'identité générée pour une table de la session en cours, sur toutes les étendues. Vous devez faire attention ici, puisque c'est à travers les portées. Vous pouvez obtenir une valeur à partir d'un déclencheur, au lieu de votre déclaration actuelle.

  • SCOPE_IDENTITY() renvoie la dernière valeur d'identité générée pour une table dans la session en cours et la portée actuelle. Généralement ce que vous voulez utiliser.

  • IDENT_CURRENT('tableName') renvoie la dernière valeur d'identité générée pour une table spécifique dans une session et une portée. Cela vous permet de spécifier la table dont vous voulez obtenir la valeur, au cas où les deux ci-dessus ne sont pas tout à fait ce dont vous avez besoin (très rare). Aussi comme @Guy Starbuck mentionné, "Vous pouvez utiliser ceci si vous voulez obtenir la valeur IDENTITY actuelle pour une table dans laquelle vous n'avez pas inséré d'enregistrement."

  • le OUTPUT clause du INSERT instruction vous permettra d'accéder à chaque ligne qui a été insérée via cette instruction. Comme il est limité à la déclaration spécifique, il est plus simple que les autres fonctions ci-dessus. Cependant, c'est un peu plus verbeux (vous aurez besoin d'insérer dans une table table variable / temp, puis interroger cela) et il donne des résultats même dans un scénario d'erreur où l'instruction est annulée. Cela dit, si votre requête utilise un plan d'exécution parallèle, ceci est le seule méthode garantie pour obtenir l'identité (à court d'éteindre le parallélisme). Cependant, il est exécuté avant déclenche et ne peut pas être utilisé pour renvoyer des valeurs générées par un déclencheur.


1171
2017-09-03 21:38



Je crois que la méthode la plus sûre et la plus précise de récupérer l'identifiant inséré serait l'utilisation de la clause de sortie.

par exemple (tiré de la suite MSDN article)

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

150
2018-05-20 14:43



Je dis la même chose que les autres, alors tout le monde a raison, j'essaie juste de le rendre plus clair.

@@IDENTITY renvoie l'ID de la dernière chose qui a été insérée par la connexion de votre client à la base de données.
La plupart du temps cela fonctionne bien, mais parfois un déclencheur ira et insérera une nouvelle ligne que vous ne connaissez pas, et vous obtiendrez l'ID de cette nouvelle ligne, au lieu de celle que vous voulez

SCOPE_IDENTITY() résout ce problème. Il renvoie l'identifiant de la dernière chose que vous avez inséré dans le code SQL tu as envoyé à la base de données. Si les déclencheurs vont créer des lignes supplémentaires, ils ne seront pas retournés. Hourra

IDENT_CURRENT renvoie le dernier identifiant qui a été inséré par n'importe qui. Si une autre application arrive à insérer une autre ligne à un moment imprévisible, vous obtiendrez l'ID de cette ligne au lieu de l'un.

Si vous voulez jouer en toute sécurité, utilisez toujours SCOPE_IDENTITY(). Si vous restez avec @@IDENTITYet quelqu'un décide d'ajouter un déclencheur plus tard, tout votre code va se casser.


94
2017-09-03 21:44



Le meilleur moyen (lire: le plus sûr) d'obtenir l'identité d'une ligne nouvellement insérée est d'utiliser le output clause:

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)

52
2018-04-29 07:22



Ajouter

SELECT CAST(scope_identity() AS int);

à la fin de votre instruction insert sql, puis

NewId = command.ExecuteScalar()

va le récupérer.


20
2018-03-30 18:25



MSDN

@@ IDENTITY, SCOPE_IDENTITY et IDENT_CURRENT sont des fonctions similaires en ce qu'ils retournent la dernière valeur insérée dans la colonne IDENTITY d'une table.

@@ IDENTITY et SCOPE_IDENTITY renvoient la dernière valeur d'identité générée dans une table de la session en cours. Toutefois, SCOPE_IDENTITY renvoie la valeur uniquement dans la portée actuelle; @@ IDENTITY n'est pas limité à une portée spécifique.

IDENT_CURRENT n'est pas limité par la portée et la session; il est limité à une table spécifiée. IDENT_CURRENT renvoie la valeur d'identité générée pour une table spécifique dans toute session et toute portée. Pour plus d'informations, voir IDENT_CURRENT.

  • IDENT_CURRENT est une fonction qui prend une table en argument.
  • @@IDENTITÉ peut renvoyer un résultat confus lorsque vous avez un déclencheur sur la table
  • SCOPE_IDENTITY est votre héros la plupart du temps.

12
2017-09-03 21:37



@@IDENTITÉ est la dernière identité insérée à l'aide de la connexion SQL actuelle. C'est une bonne valeur à renvoyer d'une procédure stockée d'insertion, où vous avez juste besoin de l'identité insérée pour votre nouvel enregistrement, et ne vous inquiétez pas si plus de lignes ont été ajoutées par la suite.

SCOPE_IDENTITY est la dernière identité insérée à l'aide de la connexion SQL actuelle et dans la portée actuelle, c'est-à-dire s'il y avait une seconde IDENTITÉ insérée sur un trigger après votre insertion, elle ne serait pas reflétée dans SCOPE_IDENTITY, uniquement l'insertion que vous avez effectuée. Franchement, je n'ai jamais eu de raison d'utiliser ça.

IDENT_CURRENT (nom_table) est la dernière identité insérée indépendamment de la connexion ou de la portée. Vous pouvez l'utiliser si vous voulez obtenir la valeur IDENTITY actuelle pour une table dans laquelle vous n'avez pas inséré d'enregistrement.


11
2017-09-03 21:42



Lorsque vous utilisez Entity Framework, il utilise en interne le OUTPUT technique pour retourner la valeur d'identification nouvellement insérée

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

Les résultats de sortie sont stockés dans une variable de table temporaire, rejoints dans la table et renvoyer la valeur de ligne hors de la table.

Note: Je ne sais pas pourquoi EF relierait la table éphémère à la table réelle (dans quelles circonstances les deux ne correspondraient pas).

Mais c'est ce que EF fait.

Cette technique (OUTPUT) n'est disponible que sur SQL Server 2008 ou plus récent.


10
2017-11-04 15:05



TOUJOURS utilisez scope_identity (), il n'y a JAMAIS besoin d'autre chose.


7
2017-10-09 20:35



Je ne peux pas parler à d'autres versions de SQL Server, mais en 2012, la sortie fonctionne directement très bien. Vous n'avez pas besoin de vous embêter avec une table temporaire.

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

Par ailleurs, cette technique fonctionne également lors de l'insertion de plusieurs lignes.

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

Sortie

ID
2
3
4

2
2018-06-06 16:58