Question

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

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

Quelqu'un peut-il expliquer les différences et quand je devrais les utiliser ?

Était-ce utile?

La solution

  • @@IDENTITY renvoie la dernière valeur d'identité générée pour n'importe quelle table de la session en cours, dans toutes les étendues. Il faut être prudent ici, car c'est à travers les portées.Vous pouvez obtenir une valeur à partir d'un déclencheur, au lieu de votre instruction actuelle.

  • SCOPE_IDENTITY() renvoie la dernière valeur d'identité générée pour n'importe quelle table de la session en cours et de la portée actuelle. Généralement, ce que vous souhaitez 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 étendue.Cela vous permet de spécifier de quelle table vous souhaitez obtenir la valeur, au cas où les deux ci-dessus ne correspondraient pas tout à fait à vos besoins (très rare).Aussi comme @Guy Starbuck a mentionné : "Vous pouvez l'utiliser si vous souhaitez obtenir la valeur IDENTITY actuelle pour une table dans laquelle vous n'avez pas inséré d'enregistrement."

  • Le OUTPUT clause de la INSERT L'instruction vous permettra d'accéder à chaque ligne insérée via cette instruction.Puisqu'il est limité à la déclaration spécifique, c'est plus simple que les autres fonctions ci-dessus.Cependant, c'est un peu plus verbeux (vous devrez l'insérer dans une variable de table/table temporaire, puis l'interroger) et cela 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, c'est le 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 renvoyer des valeurs générées par le déclencheur.

Autres conseils

Je pense que la méthode la plus sûre et la plus précise pour récupérer l'identifiant inséré consisterait à utiliser la clause de sortie.

par exemple (extrait de ce qui suit 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

Je dis la même chose que les autres, donc tout le monde a raison, j'essaie juste d'être plus clair.

@@IDENTITY renvoie l'identifiant 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 va insérer une nouvelle ligne dont vous ne connaissez pas l'existence, et vous obtiendrez l'ID de cette nouvelle ligne, au lieu de celui que vous souhaitez.

SCOPE_IDENTITY() résout ce problème.Il renvoie l'identifiant de la dernière chose qui tu as inséré dans le code SQL tu as envoyé à la base de données.Si les déclencheurs créent des lignes supplémentaires, ils n’entraîneront pas le retour d’une valeur incorrecte.Hourra

IDENT_CURRENT renvoie le dernier identifiant inséré par quelqu'un.Si une autre application insère une autre ligne à un moment malheureux, vous obtiendrez l'ID de cette ligne au lieu du vôtre.

Si vous voulez jouer la sécurité, utilisez toujours SCOPE_IDENTITY().Si tu restes avec @@IDENTITY et que quelqu'un décide d'ajouter un déclencheur plus tard, tout votre code sera brisé.

Le meilleur (lire :le moyen le plus sûr) d'obtenir l'identité d'une ligne nouvellement insérée consiste à 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)

Ajouter

SELECT CAST(scope_identity() AS int);

à la fin de votre instruction insert sql, puis

NewId = command.ExecuteScalar()

le récupérera.

MSDN

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

@@IDENTITY et SCOPE_IDENTITY renverront 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 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 n'importe quelle session et n'importe quelle étendue.Pour plus d’informations, consultez IDENT_CURRENT.

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

Lorsque vous utilisez Entity Framework, il utilise en interne le OUTPUT technique pour renvoyer 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, joints à la table et renvoient la valeur de la ligne hors de la table.

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

Mais c'est ce que fait EF.

Cette technique (OUTPUT) est uniquement disponible sur SQL Server 2008 ou version ultérieure.

@@IDENTITÉ est la dernière identité insérée à l'aide de la connexion SQL actuelle.Il s'agit d'une bonne valeur à renvoyer à partir d'une procédure stockée d'insertion, dans laquelle vous avez juste besoin d'insérer l'identité pour votre nouvel enregistrement, sans vous soucier de savoir si d'autres 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 que s'il y avait une deuxième IDENTITÉ insérée en fonction d'un déclencheur après votre insertion, elle ne serait pas reflétée dans SCOPE_IDENTITY, uniquement dans l'insertion que vous avez effectuée.Franchement, je n'ai jamais eu de raison d'utiliser ça.

IDENT_CURRENT(nom de la table) est la dernière identité insérée, quelle que soit la connexion ou la portée.Vous pouvez l'utiliser si vous souhaitez obtenir la valeur IDENTITY actuelle pour une table dans laquelle vous n'avez pas inséré d'enregistrement.

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

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

À propos, cette technique fonctionne également lors de l'insertion de plusieurs lignes.

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

Sortir

ID
2
3
4

TOUJOURS utilisez scope_identity(), vous n'avez JAMAIS besoin d'autre chose.

Après votre déclaration d'insertion, vous devez l'ajouter.Et assurez-vous du nom de la table dans laquelle les données sont insérées. Vous obtiendrez la ligne actuelle, où la ligne affectée tout à l'heure par votre instruction d'insertion.

IDENT_CURRENT('tableName')

Si vous recherchez le dernier identifiant ajouté/mis à jour, cela peut être un peu old-school, mais il y a beaucoup de gens qui utilisent un PHP plus ancien, Pre 5.5 pour être plus précis.Plus de détails peuvent être trouvés sur http://php.net/manual/en/function.mysql-insert-id.php

$last = mysql_insert_id();

Créer un uuid et insérez-le également dans une colonne.Ensuite, vous pouvez facilement identifier votre ligne avec l'uuid.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top