424 votes

SQL Server - Valeur de retour après INSERT

J'essaie de récupérer la valeur d'une clé après une instruction INSERT. Exemple : J'ai une table avec les attributs name et id. id est une valeur générée.

    INSERT INTO table (name) VALUES('bob');

Maintenant je veux récupérer l'identifiant dans la même étape. Comment cela se fait-il ?

Nous utilisons Microsoft SQL Server 2008.

0 votes

J'ai trouvé une réponse utile ici : [preparedstatement-with-statement-return-generated-keys][1] [1] : stackoverflow.com/questions/4224228/

2 votes

635voto

gbn Points 197263

Pas besoin d'un SELECT séparé...

INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');

Cela fonctionne également pour les colonnes non identitaires (telles que les GUID).

43 votes

Pourriez-vous nous en dire un peu plus ? Où va la sortie dans cet exemple ? La documentation ne montre que des exemples pour les tableaux (en utilisant output... into). Idéalement, j'aimerais pouvoir le passer dans une variable.

3 votes

@JonnyLeeds : vous ne pouvez pas le faire sur une variable (sauf si c'est une variable de table). La SORTIE va au client ou à une table.

9 votes

Malheureusement, vous ne pouvez pas compter sur cela, car l'ajout d'un déclencheur à la table brisera vos déclarations ! re : blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/

257voto

Curt Points 42871

Utilisez SCOPE_IDENTITY() pour obtenir la nouvelle valeur de l'ID

INSERT INTO table (name) VALUES('bob');

SELECT SCOPE_IDENTITY()

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

14 votes

@liho1eye - Le PO a fait référence au nom de la colonne d'identité en tant que id donc oui.

5 votes

Sur un grand système, que se passe-t-il si de nombreux sql sont exécutés en même temps ? Le système renverra-t-il le dernier identifiant inséré à chaque requête ?

6 votes

@Shiv "SCOPE_IDENTITY renvoie les valeurs insérées uniquement dans la portée actuelle".

57voto

hajikelist Points 53
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY();

C'est la solution la plus sûre car il existe un problème connu de conflit avec la clause OUTPUT sur les tables avec des déclencheurs. Cela rend l'application peu fiable, car même si votre table n'a pas actuellement de déclencheurs, quelqu'un qui en ajouterait un par la suite casserait votre application. Une sorte de comportement de bombe à retardement.

Voir l'article msdn pour une explication plus approfondie :

http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx

40voto

Ian Boyd Points 50743

Entity Framework effectue quelque chose de similaire à la réponse de gbn :

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO Customers(FirstName)
OUTPUT inserted.CustomerID INTO @generated_keys
VALUES('bob');

SELECT t.[CustomerID]
FROM @generated_keys AS g 
   JOIN dbo.Customers AS t 
   ON g.Id = t.CustomerID
WHERE @@ROWCOUNT > 0

Les résultats de la sortie sont stockés dans une variable de table temporaire, puis sélectionnés pour être renvoyés au client. Il faut être conscient de ce piège :

les insertions peuvent générer plus d'une ligne, donc la variable peut contenir plus d'une ligne, donc vous pouvez recevoir plus d'une ligne. ID

Je ne vois pas pourquoi EF joindrait intérieurement la table éphémère à la table réelle (dans quelles circonstances les deux ne correspondraient pas).

Mais c'est ce que fait EF.

SQL Server 2008 ou plus récent uniquement. Si c'est 2005, vous n'avez pas de chance.

24voto

Reza Jenabi Points 116

Il existe plusieurs façons de sortir après l'insertion

Lorsque vous insérez des données dans une table, vous pouvez utiliser la clause OUTPUT pour renvoyer une copie des données qui ont été insérées dans la table. La clause clause OUTPUT prend deux formes de base : OUTPUT et OUTPUT INTO. Utilisez la forme OUTPUT si vous souhaitez renvoyer les données à l'application appelante. Utilisez la forme OUTPUT INTO si vous souhaitez renvoyer les données dans une table ou une variable de table.

DECLARE @MyTableVar TABLE (id INT,NAME NVARCHAR(50));

INSERT INTO tableName
(
  NAME,....
)OUTPUT INSERTED.id,INSERTED.Name INTO @MyTableVar
VALUES
(
   'test',...
)

IDENT_CURRENT : Il renvoie la dernière identité créée pour une table ou une vue particulière dans une session quelconque.

SELECT IDENT_CURRENT('tableName') AS [IDENT_CURRENT]

SCOPE_IDENTITÉ : Il renvoie la dernière identité d'une même session et d'une même portée. Une portée est une procédure stockée/un déclencheur, etc.

SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];  

@@IDENTITÉ : Elle renvoie la dernière identité de la même session.

SELECT @@IDENTITY AS [@@IDENTITY];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X