Quelle est la meilleure option pour obtenir la valeur d’identité que je viens de générer via un insert? Quel est l'impact de ces déclarations en termes de performance?
SCOPE_IDENTITY()
- Fonction d'agrégat
MAX()
- SELECT
TOP 1
IdentityColumn FROM TableNameORDER BY IdentityColumn DESC
Réponses:
Utilisez cette option
SCOPE_IDENTITY()
si vous insérez une seule ligne et souhaitez récupérer l'ID généré.Résultat:
Utilisez la
OUTPUT
clause si vous insérez plusieurs lignes et devez récupérer l' ensemble des ID générés.Résultat:
Les performances mises à part, ce sont les seuls qui sont garantis d'être corrects dans le niveau d'isolation par défaut et / ou avec plusieurs utilisateurs. Même si vous ignorez l'aspect de la correction, SQL Server conserve la valeur insérée
SCOPE_IDENTITY()
en mémoire. Ce sera donc naturellement plus rapide que de lancer votre propre requête isolée sur la table ou sur les tables système.Ignorer l'aspect correction est comme dire au facteur qu'il a bien fait de livrer le courrier d'aujourd'hui: il a terminé son parcours 10 minutes plus rapidement que son temps moyen, le problème est qu'aucun courrier n'a été livré à la bonne maison.
N'utilisez aucun des éléments suivants:
@@IDENTITY
- dans la mesure où cela ne peut pas être utilisé dans tous les scénarios, par exemple, lorsqu'une table avec une colonne d'identité a un déclencheur qui est également inséré dans une autre table avec sa propre colonne d'identité - vous obtiendrez la mauvaise valeur.IDENT_CURRENT()
- Je vais entrer dans les détails à ce sujet ici , et les commentaires sont aussi une lecture utile, mais essentiellement, en cas de concurrence, vous obtiendrez souvent une mauvaise réponse.MAX()
ouTOP 1
- vous devez protéger les deux déclarations avec un isolement sérialisable afin de vous assurer que ce queMAX()
vous obtenez n'est pas celui de quelqu'un d'autre. C'est beaucoup plus cher que de simplement utiliserSCOPE_IDENTITY()
.Ces fonctions échouent également chaque fois que vous insérez deux lignes ou plus et requièrent toutes les valeurs d'identité générées. Votre seule option est la
OUTPUT
clause.la source
En dehors de la performance, ils ont tous des significations assez différentes.
SCOPE_IDENTITY()
vous donnera la dernière valeur d'identité insérée dans une table directement dans l'étendue actuelle (scope = batch, procédure stockée, etc., mais pas à l'intérieur, par exemple, d'un déclencheur déclenché par l'étendue actuelle).IDENT_CURRENT()
vous donnera la dernière valeur d'identité insérée dans une table spécifique à partir de n'importe quelle portée, par n'importe quel utilisateur.@@IDENTITY
vous donne la dernière valeur d'identité générée par l'instruction INSERT la plus récente pour la connexion en cours, indépendamment de la table ou de la portée. (Remarque: Access utilise cette fonction et présente donc quelques problèmes avec les déclencheurs qui insèrent des valeurs dans des tables avec des colonnes d'identité.)L'utilisation de
MAX()
ouTOP 1
peut vous donner des résultats totalement erronés si la table comporte une étape d'identité négative ou si des lignes ont été inséréesSET IDENTITY_INSERT
. Voici un script démontrant toutes ces choses:Résumé: restez avec
SCOPE_IDENTITY()
,IDENT_CURRENT()
ou@@IDENTITY
, et assurez-vous d’utiliser celui qui vous renvoie ce dont vous avez réellement besoin.la source
IDENT_CURRENT()
et@@IDENTITY
lorsque votre propre script démontre qu'il génère des résultats incorrects?IDENT_CURRENT()
revient. MAX () ne renvoie jamais la valeur correcte au-delà de la première ligne, puisque id compte en arrière et , par conséquentIDENTITY_INSERT
, 9005 n'est pas une valeur d'identité générée et n'est donc pas reflétéeIDENT_CURRENT()
. Mais il peut retourner des résultats "incorrects" si vous voulez vraiment ce quiSCOPE_IDENTITY()
revient. Choisissez le bon outil pour le travail.@@IDENTITY
n’est presque jamais le moyen idéal d’obtenir des valeurs d’identité générées. Le point principal est queMAX()
ouTOP 1
sont comme une version moins fiable deIDENT_CURRENT()
, ce qui est une fonction parfaitement utile à utiliser si vous comprenez ce qu’elle fait. Pourrait être utile pour des travaux de maintenance ou autre chose.