2009-06-10 5 views
11

Je m'insère dans une table SQLServer avec un champ clé auto-incrémenté. (Je crois que ce qu'on appelle une colonne IDENTITY dans SQLServer.)Comment renvoyer une nouvelle valeur de colonne IDENTITY à partir d'une instruction SQLServer SELECT?

Dans Oracle, je peux utiliser le mot-clé RETOURNER pour donner mon instruction INSERT un jeu de résultats comme une requête SELECT qui renverra la valeur générée:

INSERT INTO table 
(foreign_key1, value) 
VALUES 
(9, 'text') 
RETURNING key_field INTO :var; 

Comment j'accomplis cela dans SQLServer?

Bonus: Bon, bonnes réponses jusqu'à maintenant, mais comment le mettre en une seule déclaration, si possible? :)

+0

Ajout de l'exemple "un appel". – gbn

Répondre

17

En général, cela ne peut pas être fait dans une seule instruction. Mais le SELECT SCOPE_IDENTITY() peut (et devrait) être placé directement après l'instruction INSERT, donc tout est fait dans le même appel de base de données.

Exemple:

mydb.ExecuteSql("INSERT INTO table(foreign_key1, value) VALUES(9, 'text'); SELECT SCOPE_IDENTITY();"); 

Vous pouvez utiliser la sortie, mais il a quelques limitations que vous devriez être au courant:

http://msdn.microsoft.com/en-us/library/ms177564.aspx

+4

Incroyable. Je n'avais aucune idée que je pourrais combiner des déclarations comme ça. Intelligent, non-standard, hideux, utile ... tous ces adjectifs me viennent à l'esprit. :) – skiphoppy

+1

Il peut être fait dans une instruction SQL Server 2005 avec la sortie – gbn

9
SELECT SCOPE_IDENTITY() 

Edit: Avoir un jeu ...

Si seulement la clause OUTPUT pris en charge les variables locales.

Quoi qu'il en soit, pour obtenir une plage d'ID plutôt que d'un singleton

DECLARE @Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50)) 

INSERT @Mytable (valuecol) 
OUTPUT Inserted.keycol 
SELECT 'harry' 
UNION ALL 
SELECT 'dick' 
UNION ALL 
SELECT 'tom' 

Edit 2: Dans un appel. Je n'ai jamais eu l'occasion d'utiliser cette construction.

DECLARE @Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50)) 

INSERT @Mytable (valuecol) 
OUTPUT Inserted.keycol 
VALUES('foobar') 
+0

Je seconde ceci. SCOPE_IDENTITY() renvoie l'identité la plus récente dans la portée de votre requête la plus récente. Autres méthodes @@ IDENTITY et IDENT_CURRENT() ne sont pas limitées à une portée spécifique –

+0

hhmm un downvote anonyme pour cette réponse ... – gbn

2

SCOPE_IDENTITY

4

En plus de @@ IDENTITY, vous devriez également regarder dans SCOPE_IDENTITY() et IDENT_CURRENT(). Vous voulez probablement SCOPE_IDENTITY(). @@ IDENTITY a un problème en ce sens qu'il peut renvoyer une valeur d'identité créée dans un déclencheur sur la table réelle que vous essayez de suivre.

De plus, il s'agit de fonctions à valeur unique. Je ne sais pas comment fonctionne le mot-clé Oracle RETURNING.

0

Vous pouvez utiliser OUTPUT INTO, ce qui présente l'avantage supplémentaire de pouvoir capturer plusieurs identités insérées.

0

INSERT INTO table (foreign_key1, valeur) VALUES (9, 'texte'); SELECT @@ IDENTITY;

2

Cela dépend de votre contexte d'appel.

Si vous appelez ceci à partir du code client, vous pouvez utiliser OUTPUT, puis lire la valeur renvoyée.

DECLARE @t TABLE (ColID int IDENTITY, ColStr varchar(20)) 

INSERT INTO @t (ColStr) 
OUTPUT Inserted.ColID 
VALUES ('Hello World') 

Résultat:

 ColID 
----------- 
      1 

Si vous envelopper cela dans une procédure stockée, en utilisant la sortie est plus de travail. Là, vous voulez utiliser SCOPE_IDENTITY(), mais vous ne pouvez pas le faire dans une seule instruction. Bien sûr, vous pouvez mettre plusieurs instructions sur une seule ligne avec un ';' séparateur, mais ce n'est pas une seule déclaration.

DECLARE @idValue int 
DECLARE @t TABLE (ColID int IDENTITY, ColStr varchar(20)) 

INSERT INTO @t (ColStr) VALUES ('Hello World') 

SELECT @idValue = SCOPE_IDENTITY() 

Résultat: La variable @idValue contient une valeur d'identité. Utilisez un paramètre OUTPUT pour renvoyer la valeur.

Questions connexes