Comment utiliser la clause OUTPUT d'une instruction INSERT pour obtenir la valeur d'identité?

240

Si j'ai une instruction d'insertion telle que:

INSERT INTO MyTable
(  
  Name,
  Address,
  PhoneNo
)
VALUES
(
  'Yatrix',
   '1234 Address Stuff',
   '1112223333'
)

Comment définir @var INTla valeur d'identité de la nouvelle ligne (appelée Id) à l'aide de la clause OUTPUT? J'ai vu des exemples de mise INSERTED.Name dans des variables de table, par exemple, mais je ne peux pas le mettre dans une variable non-table.

J'ai essayé OUPUT INSERTED.Id AS @var, SET @var = INSERTED.Idmais aucun n'a fonctionné.

Yatrix
la source
3
Je connais déjà @@ SCOPE_IDENTITY, je veux spécifiquement savoir comment le faire avec OUPUT. Merci.
Yatrix
6
Vous devez l'insérer dans une variable de table, puis faire votre sélection. Il n'y a pas de syntaxe à attribuer directement à une variable scalaire de la OUTPUTclause.
Martin Smith
3
La clause OUTPUT doit sortir dans une table ou une variable de table.
mellamokb
5
La OUTPUTclause écrit dans une table. Il peut s'agir d'une variable de table, d'une table temporaire, ....
HABO
2
Ma question demande spécifiquement la clause OUTPUT.
Yatrix

Réponses:

464

Vous pouvez soit avoir l'ID nouvellement inséré en sortie sur la console SSMS comme ceci:

INSERT INTO MyTable(Name, Address, PhoneNo)
OUTPUT INSERTED.ID
VALUES ('Yatrix', '1234 Address Stuff', '1112223333')

Vous pouvez également l'utiliser à partir de C #, par exemple, lorsque vous devez récupérer l'ID dans votre application appelante - exécutez simplement la requête SQL avec .ExecuteScalar()(au lieu de .ExecuteNonQuery()) pour lire le résultat ID.

Ou si vous devez capturer le nouveau fichier inséré IDdans T-SQL (par exemple pour un traitement ultérieur), vous devez créer une variable de table:

DECLARE @OutputTbl TABLE (ID INT)

INSERT INTO MyTable(Name, Address, PhoneNo)
OUTPUT INSERTED.ID INTO @OutputTbl(ID)
VALUES ('Yatrix', '1234 Address Stuff', '1112223333')

De cette façon, vous pouvez insérer plusieurs valeurs @OutputTblet effectuer un traitement supplémentaire sur celles-ci. Vous pouvez également utiliser ici une table temporaire "régulière" ( #temp) ou même une "vraie" table persistante comme "cible de sortie".

marc_s
la source
2
La réponse ici pour le code derrière était concise. ExecuteScalar () FTW
Joe Johnston
10
Vous pouvez insérer le résultat dans un real persistent table- c'est extrêmement fantastique car cela signifie que vous pouvez INSERTen TWOmême temps obtenir des informations dans des tableaux.
gotqn
7
N'utilisez jamais @@ IDENTITY pour tirer du haut. Foudrez-vous à travailler dur avec les déclencheurs et comme ils enregistraient l'historique des modifications apportées à une table et les inséraient dans une nouvelle table en même temps, @@ IDENTITY a commencé à renvoyer des valeurs de la table d'historique. l'hilarité en découle! Veuillez utiliser la solution de marc_s. pour le moment, j'ai opté pour la méthode @OutputTbl, mais je suis intrigué par les autres options.
Eric Bishard
4
OUTPUT INTO est extrêmement fantastique, sauf que «la table cible de la clause OUTPUT INTO ne peut pas être de part et d'autre d'une relation (clé primaire, clé étrangère)», ce qui représente pour moi environ 99% des cas d'utilisation potentiels. Je suppose que cela est dû au fait que la clause OUTPUT peut renvoyer des données même lorsque la transaction est annulée, mais c'est un peu ennuyeux qu'il est si difficile d'insérer dans les données dans les tables connexes A et B en une seule fois.
Robert Calhoun
3
@EricBishard SCOPE_IDENTITY()fonctionne mieux pour cela.
Derreck Dean le