Meilleure façon d'obtenir l'identité de la ligne insérée?

Quelle est la meilleure façon d'obtenir IDENTITY de la rangée insérée?

je connais @@IDENTITY et IDENT_CURRENT et SCOPE_IDENTITY mais je ne comprends pas le pour et le contre attachés à chacun.

est-ce que quelqu'un peut expliquer les différences et quand je devrais les utiliser?

910
demandé sur DineshDB 2008-09-04 01:32:02

11 réponses

  • @@IDENTITY renvoie la dernière valeur d'identité générée pour n'importe quelle table de la session courante, dans tous les domaines. vous devez être prudent ici , car il 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 n'importe quelle table session en cours et 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 n'importe quelle session et n'importe quelle portée. Cela vous permet de spécifier de quelle table vous voulez la valeur, dans le 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 D'identité courante pour une table dans laquelle vous n'avez pas inséré un enregistrement."

  • la OUTPUT clause de la déclaration INSERT vous permettra d'accéder à chaque ligne qui a été insérée via cette déclaration. Comme il est scoped à l'énoncé 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 variable/temp table et puis interrogation que) et il donne des résultats même dans un scénario d'erreur où l'énoncé est retranché. Cela dit, si votre requête utilise un plan d'exécution parallèle, il s'agit de la seule méthode garantie pour obtenir l'identité (à moins de désactiver le parallélisme). Cependant, il est exécuté avant déclencheurs et ne peut pas être utilisé pour retourner déclencheur généré valeur.

1202
répondu bdukes 2017-05-23 12:02:48

je crois que la méthode la plus sûre et la plus précise pour récupérer l'id inséré serait d'utiliser la clause de sortie.

par exemple (tiré de l'article suivant MSDN )

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
156
répondu Orry 2011-05-20 15:11:28

je dis la même chose que les autres gars, donc 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 très bien, mais parfois un déclencheur va et insérer une nouvelle ligne que vous ne connaissez pas, et vous obtiendrez L'ID de cette nouvelle ligne, au lieu de celui que vous voulez

SCOPE_IDENTITY() résout ce problème. Il renvoie l'id de la dernière chose que vous avez insérée dans le code SQL que vous avez envoyé à la base de données. Si les déclencheurs vont et créent des lignes supplémentaires, ils ne causeront pas la mauvaise valeur pour être retournés. Hourra

IDENT_CURRENT renvoie la dernière ID qui a été insérée par quelqu'un. Si une autre application arrive à insérer une autre ligne à un moment Non choisi, vous obtiendrez L'ID de cette ligne au lieu de votre.

si vous voulez jouer en toute sécurité, Utilisez toujours SCOPE_IDENTITY() . Si vous vous en tenez à @@IDENTITY et que quelqu'un décide d'ajouter un déclencheur plus tard, tout votre code se brisera.

97
répondu Orion Edwards 2008-09-03 21:44:50

le meilleur (lire: le plus sûr) moyen d'obtenir l'identité d'une ligne nouvellement insérée est en utilisant la 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)
55
répondu Ian Kemp 2017-11-06 12:26:21

ajouter

SELECT CAST(scope_identity() AS int);

à la fin de votre instruction sql insert, puis

NewId = command.ExecuteScalar()

le récupérera.

21
répondu Jim 2016-07-26 14:12:50

MSDN

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

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

IDENT_CURRENT n'est pas limitée par l'étendue et la session; elle est limitée à une table spécifiée. IDENT_CURRENT retourne la valeur d'identité générée pour une table spécifique dans n'importe quelle session et n'importe quelle portée. Pour en savoir plus, lisez IDENT_CURRENT.

12
répondu Jakub Šturc 2008-09-03 21:37:02

@@IDENTITY est la dernière identité insérée en utilisant la connexion SQL actuelle. C'est une bonne valeur pour retourner d'une procédure stockée insert, où vous avez juste besoin de l'identité insérée pour votre nouvel enregistrement, et ne vous souciez pas si plus de lignes ont été ajoutées après.

SCOPE_IDENTITY est la dernière identité insérée en utilisant la connexion SQL actuelle, et dans la portée actuelle -- c'est-à-dire s'il y avait une deuxième identité inséré sur la base d'un déclencheur après votre insertion, il ne serait pas reflété dans SCOPE_IDENTITY, seulement l'insertion que vous avez effectuée. Franchement, je n'ai jamais eu une raison de l'utiliser.

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

12
répondu Guy Starbuck 2017-10-10 21:23:44

lorsque vous utilisez Entity Framework, il utilise en interne la technique OUTPUT pour retourner la valeur D'ID 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, joint de nouveau à la table, et retourner la valeur de ligne hors de la table.

Note: je n'ai aucune idée de la raison pour laquelle EF inner joindrait la table éphémère de nouveau à la table réelle (dans quelles circonstances les deux ne correspondraient pas).

Mais C'est ce que fait EF.

cette technique ( OUTPUT ) n'est disponible que sur SQL Server 2008 ou une version plus récente.

11
répondu Ian Boyd 2016-11-04 15:05:48

TOUJOURS utilisation scope_identity(), il n'y a JAMAIS un besoin de rien d'autre.

7
répondu erikkallen 2009-10-09 20:35:00

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

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

soit dit en passant, cette technique fonctionne également lors de l'insertion de lignes multiples.

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

sortie

ID
2
3
4
5
répondu MarredCheese 2018-06-06 16:58:15

après votre Insertion, vous devez ajouter ceci. Et assurez-vous du nom de la table où les données sont insérées.Vous obtiendrez ligne actuelle pas de ligne affectée par votre instruction insert.

IDENT_CURRENT('tableName')
0
répondu Khan Ataur Rahman 2017-12-31 06:04:43