Quelle est la meilleure façon d'obtenir la IDENTITY
ligne insérée?
Je connais @@IDENTITY
et IDENT_CURRENT
et SCOPE_IDENTITY
mais je ne comprends pas les avantages et les inconvénients attachés à chacun.
Quelqu'un peut-il expliquer les différences et quand dois-je les utiliser?
sql
sql-server
tsql
Oded
la source
la source
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)
, ou une méthode plus ancienne:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
vous pouvez l'obtenir en c # en utilisant ExecuteScalar ().OUTPUT
clause dans SQL Server.Réponses:
@@IDENTITY
renvoie la dernière valeur d'identité générée pour n'importe quelle table de la session en cours, sur toutes les étendues. Vous devez être prudent ici , car il s'agit de plusieurs étendues. 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 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 une session et une étendue. Cela vous permet de spécifier de quelle table vous voulez que la valeur provienne, au cas où les deux ci-dessus ne seraient pas tout à fait ce dont vous avez besoin ( très rare ). En outre, comme l'a mentionné @ Guy Starbuck , "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."La
OUTPUT
clause de l'INSERT
instruction vous permettra d'accéder à chaque ligne insérée via cette instruction. Puisqu'il est limité à l'instruction spécifique, il est plus simple que les autres fonctions ci-dessus. Cependant, c'est un peu plus verbeux (vous devrez insérer dans une table variable / temp, puis interroger cela) 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 la seule méthode garantie pour obtenir l'identité (à moins de désactiver le parallélisme). Cependant, il est exécuté avant les déclencheurs et ne peut pas être utilisé pour renvoyer des valeurs générées par les déclencheurs.la source
output
vous n'avez pas besoin de créer une table temporaire pour stocker et interroger les résultats. Laissez simplement lainto
partie de la clause de sortie et il les affichera dans un jeu de résultats.OUTPUT
dire la «meilleure» tant que vous n'utilisez pas de déclencheurs et ne gérez pas d'erreurs, maisSCOPE_IDENTITY
c'est la plus simple et très rarement des problèmesJe pense que la méthode la plus sûre et la plus précise pour récupérer l'identifiant inséré serait d'utiliser la clause de sortie.
par exemple (extrait de l' article MSDN suivant )
la source
OUTPUT
dans SQL Server 2005 , il semble donc que ce soit juste SQL Server 2000 etJe dis la même chose que les autres gars, donc tout le monde a raison, j'essaie juste d'être 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'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 feront pas renvoyer la mauvaise valeur. HourraIDENT_CURRENT
renvoie le dernier ID qui a été inséré par quiconque. Si une autre application insère une autre ligne à un moment imprévu, vous obtiendrez l'ID de cette ligne au lieu de la vôtre.Si vous voulez jouer en toute sécurité, utilisez toujours
SCOPE_IDENTITY()
. Si vous restez avec@@IDENTITY
et que quelqu'un décide d'ajouter un déclencheur plus tard, tout votre code se cassera.la source
La meilleure façon (lire: la plus sûre) d'obtenir l'identité d'une ligne nouvellement insérée est d'utiliser la
output
clause:la source
scope_identity()
) obtiennent de toute façon des plans parallèles. Et ce bug a été corrigé plus d'un an avant cette réponse.output
place descope_identity()
. J'ai supprimé le FUD sur le clustering dans la réponse.Ajouter
à la fin de votre instruction SQL d'insertion, puis
va le récupérer.
la source
Lorsque vous utilisez Entity Framework, il utilise en interne la
OUTPUT
technique pour renvoyer la valeur d'ID nouvellement inséréeLes résultats de sortie sont stockés dans une variable de table temporaire, rejoints à la table et renvoient la valeur de ligne hors de la table.
Remarque: Je n'ai aucune idée de la raison pour laquelle EF fusionnerait intérieurement la table éphémère à la table réelle (dans quelles circonstances les deux ne correspondraient-elles pas).
Mais c'est ce que fait EF.
Cette technique (
OUTPUT
) n'est disponible que sur SQL Server 2008 ou plus récent.Modifier - La raison de la jointure
La raison pour laquelle Entity Framework rejoint la table d'origine, plutôt que d'utiliser simplement les
OUTPUT
valeurs, c'est que EF utilise également cette technique pour obtenir larowversion
ligne nouvellement insérée.Vous pouvez utiliser la concurrence optimiste dans vos modèles de structure d'entité en utilisant l'
Timestamp
attribut: 🕗Lorsque vous faites cela, Entity Framework aura besoin
rowversion
de la ligne nouvellement insérée:Et pour récupérer cela,
Timetsamp
vous ne pouvez pas utiliser deOUTPUT
clause.C'est parce que s'il y a un déclencheur sur la table, tout
Timestamp
SORTIE sera faux:L'horodatage renvoyé ne sera jamais correct si vous avez un déclencheur sur la table. Vous devez donc utiliser un autre
SELECT
.Et même si vous vouliez subir une version de ligne incorrecte, l'autre raison pour effectuer une séparation distincte
SELECT
est que vous ne pouvez pas SORTIR arowversion
dans une variable de table:La troisième raison de le faire est la symétrie. Lorsque vous effectuez une opération
UPDATE
sur une table avec un déclencheur, vous ne pouvez pas utiliser deOUTPUT
clause. Essayer de faireUPDATE
avec unOUTPUT
n'est pas pris en charge et donnera une erreur:La seule façon de le faire est avec une
SELECT
déclaration de suivi :la source
TurboEncabulators
:)MSDN
la source
@@ IDENTITY 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, 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 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 deuxième IDENTITY insérée basée sur un déclencheur après votre insertion, elle ne serait pas reflétée dans SCOPE_IDENTITY, seulement l'insertion que vous avez effectuée . Franchement, je n'ai jamais eu de raison de l'utiliser.
IDENT_CURRENT (tablename) 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.
la source
Je ne peux pas parler d'autres versions de SQL Server, mais en 2012, la sortie directe fonctionne très bien. Vous n'avez pas besoin de vous soucier d'une table temporaire.
Soit dit en passant, cette technique fonctionne également lors de l'insertion de plusieurs lignes.
Production
la source
OUTPUT
. Si vous n'avez pas besoin de la table temporaire, votre requête finit par être beaucoup plus simple.Utilisez TOUJOURS scope_identity (), il n'y a JAMAIS besoin d'autre chose.
la source
Créez un
uuid
et insérez-le également dans une colonne. Ensuite, vous pouvez facilement identifier votre ligne avec l'uuid. C'est la seule solution 100% fonctionnelle que vous pouvez implémenter. Toutes les autres solutions sont trop compliquées ou ne fonctionnent pas dans les mêmes cas de bord. Par exemple:1) Créer une ligne
2) Obtenez la ligne créée
la source
uuid
dans la base de données. Ainsi, la ligne sera trouvée plus rapidement.https://www.npmjs.com/package/uuid
.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()
Une autre façon de garantir l'identité des lignes que vous insérez est de spécifier les valeurs d'identité et d'utiliser le
SET IDENTITY_INSERT ON
puisOFF
. Cela garantit que vous savez exactement quelles sont les valeurs d'identité! Tant que les valeurs ne sont pas utilisées, vous pouvez insérer ces valeurs dans la colonne d'identité.Cela peut être une technique très utile si vous chargez des données d'une autre source ou fusionnez des données de deux bases de données, etc.
la source
Même s'il s'agit d'un thread plus ancien, il existe une nouvelle façon de le faire qui évite certains des pièges de la colonne IDENTITY dans les anciennes versions de SQL Server, comme les lacunes dans les valeurs d'identité après le redémarrage du serveur . Les séquences sont disponibles dans SQL Server 2016 et les versions ultérieures, la façon la plus récente consiste à créer un objet SEQUENCE à l'aide de TSQL. Cela vous permet de créer votre propre objet de séquence numérique dans SQL Server et de contrôler son incrémentation.
Voici un exemple:
Ensuite, dans TSQL, vous procéderiez comme suit pour obtenir l'ID de séquence suivant:
Voici les liens vers CREATE SEQUENCE et NEXT VALUE FOR
la source
Après votre déclaration d'insertion, vous devez l'ajouter. Et assurez-vous du nom de la table où les données sont insérées. Vous obtiendrez la ligne actuelle non où la ligne est affectée à l'instant par votre instruction d'insertion.
la source