SQL Server - Rückgabewert nach INSERT

Ich versuche, nach einer INSERT-Anweisung den Schlüsselwert zurück zu bekommen. Beispiel: Ich habe eine Tabelle mit den Attributen name und id. id ist ein generierter Wert.

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

Jetzt möchte ich die ID im selben Schritt zurückbekommen. Wie wird das gemacht?

Wir verwenden Microsoft SQL Server 2008.

211
hinzugefügt der Autor Vladimir Vagaytsev, Quelle
Ich habe hier eine sinnvolle Antwort gefunden: [preparedstatement-with-statement-return-generated-keys] [1] [1]: stackoverflow.com/questions/4224228/…
hinzugefügt der Autor Lars Ladegaard, Quelle

10 Antworten

Keine Notwendigkeit für ein separates SELECT ...

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

Dies funktioniert auch für Nicht-IDENTITY-Spalten (z. B. GUIDs)

343
hinzugefügt
Hey, hast du SO/SE gegeben? Dein letzter Beitrag war am 14. Dezember. Da kommen nur Kommentare dazu.
hinzugefügt der Autor abatishchev, Quelle
@JonnyLeeds: Sie können es nicht mit einer Variablen tun (außer einer Tabellenvariablen). Das OUTPUT geht an den Client oder eine Tabelle
hinzugefügt der Autor gbn, Quelle
@hajikelist: das ist ein ziemlich Randfall, SET NCOOUNT ON im Trigger hilft normalerweise. Siehe stackoverflow.com/questions/1483732/set-nocount-on-usage
hinzugefügt der Autor gbn, Quelle
Verwenden Sie niemals @@ IDENTITY. SCOPE_IDENTITY, ja, aber niemals @@ IDENTITY. Es ist unzuverlässig
hinzugefügt der Autor gbn, Quelle
Könntest du ein wenig weiterarbeiten? Wohin geht der Output in diesem Beispiel? Die Dokumentation zeigt nur Beispiele für Tabellen (mit output ... in ). Im Idealfall möchte ich es einfach in eine Variable übergeben können
hinzugefügt der Autor Jonny Leeds, Quelle
Sie können auch @@ IDENTITY und andere verwenden. Und die Klauselordnung ist wichtig! (fand den harten Weg ..)
hinzugefügt der Autor Z. Khullah, Quelle
@gbn stimme ich nicht zu - Auslöser sind sehr häufig. Ich bin mir nicht sicher, ob das Einstellen von NOCOUNT das korrigiert, bitte lesen Sie diesen msdn-Beitrag für eine tiefere Erklärung durch.
hinzugefügt der Autor hajikelist, Quelle
Leider können Sie sich nicht darauf verlassen, da das Hinzufügen eines Triggers zur Tabelle Ihre Anweisungen bricht! re: blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/…
hinzugefügt der Autor hajikelist, Quelle

Verwenden Sie SCOPE_IDENTITY() , um den neuen ID-Wert zu erhalten

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

SELECT SCOPE_IDENTITY()

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

126
hinzugefügt
@ liho1eye - Das OP bezieht sich auf den Identitätsspaltennamen als id , also ja.
hinzugefügt der Autor Curt, Quelle
Angenommen, id ist Identität
hinzugefügt der Autor Ilia G, Quelle
Auf einem größeren System: Was passiert, wenn vieleSQL-servergleichzeitig ausgeführt werden? Gibt es die letzte eingefügte ID für jede Anfrage zurück?
hinzugefügt der Autor Shiv, Quelle
@Shiv "SCOPE_IDENTITY gibt nur innerhalb des aktuellen Bereichs eingefügte Werte zurück"
hinzugefügt der Autor goodies4uall, Quelle
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY();

Dies ist die sicherste Wette, da bei Tabellen mit Triggern ein Problem mit dem OUTPUT-Klausel-Konflikt bekannt ist. Macht dies ziemlich unzuverlässig, selbst wenn Ihr Tisch momentan keine Auslöser hat - jemand, der einen nach dem anderen hinzufügt, wird Ihre Anwendung zerstören. Zeitbombe Art von Verhalten.

Siehe MSDN Artikel für tiefergehende Erklärung:

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

30
hinzugefügt
@hajikelist Wir alle haben Vermächtnis, aber das Risiko von Triggern messing OUTPUT ist niedrig, alles, was es braucht, Nocount gesetzt ist. Wenn jemand einen Trigger hinzufügt, sollte er wissen, wie er diesen Code schreiben soll (das heißt, Sie haben hauptsächlich die Kontrolle), oder Sie müssen Ihre Entwickler schulen. Irgendwann werden Sie gezwungen sein, zu migrieren, wenn diese Version von SQL nicht mehr existiert unterstützt usw., so dass Trigger keine Ergebnismenge verursachen. Wie auch immer, es ist nicht die beste Antwort, denn wenn Sie INSTEAD OF-Trigger haben, funktioniert die SCOPE_IDENTITY möglicherweise nicht (SQL-serververliert die Bereichsidentität% 23 "> stackoverflow.com/questions/908257/… )
hinzugefügt der Autor gbn, Quelle
Nur wenn Sie SET NOCOUNT ON nicht in Triggern hinzufügen. Siehe auch docs.microsoft.com/en-us/sql/database-engine/configure-windo&zwwnj; ws/& hellip;
hinzugefügt der Autor gbn, Quelle
Dies ist keine Option für unsere Legacy-Umgebungen @gbn
hinzugefügt der Autor hajikelist, Quelle
@ Gbn - Ich mag nur solche dummen Dinge zu vermeiden. Ich werde nicht allen meinen Entwicklern sagen: "Vergessen Sie nicht, in jedem Trigger die Anweisung, Bitte nicht meine App abbrechen 'hinzuzufügen." - du kannst es behalten. Das "stattdessen" -Szenario ist viel mehr ein Grenzfall.
hinzugefügt der Autor hajikelist, Quelle

Entity Framework führt etwas ähnlich der Antwort von gbn aus:

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

Die Ausgabeergebnisse werden in einer temporären Tabellenvariablen gespeichert und dann zum Client zurückgewählt. Berücksichtigen Sie die Frage:

-Einfügungen können mehr als eine Zeile generieren, sodass die Variable mehr als eine Zeile enthalten kann, sodass Sie mehr als eine ID

zurückgeben können

Ich habe keine Ahnung, warum EF innerlich den ephemeren Tisch wieder an den realen Tisch anschließen würde (unter welchen Umständen würden die beiden nicht zusammenpassen).

Aber genau das macht EF.

Nur SQL Server 2008 oder neuer. Wenn es 2005 ist, dann hast du kein Glück.

12
hinzugefügt

@@ IDENTITY Ist eine Systemfunktion, die den zuletzt eingefügten Identitätswert zurückgibt.

7
hinzugefügt
Ich rate davon ab, jemals @@ IDENTITY zu verwenden - es ist nicht genau (zu weit) viel weniger Thread-sicher - siehe @ Curt's Antwort über SCOPE_IDENTITY ().
hinzugefügt der Autor zanlok, Quelle

After doing an insert into a table with an identity column, you can reference @@IDENTITY to get the value: http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx

5
hinzugefügt
ja, benutze es nie. Es funktioniert nicht immer gut: X
hinzugefügt der Autor H.Ghassami, Quelle
Benutze niemals @@ IDENTITY: es ist nicht sicher für den Umfang: triggert usw. und beeinflusst es.
hinzugefügt der Autor gbn, Quelle

Sie können scope_identity verwenden, um die ID der Zeile auszuwählen, die Sie gerade in eine Variable eingefügt haben, und dann einfach die gewünschten Spalten aus der Tabelle auswählen, wobei id = die Identität ist, die Sie von scope_identity erhalten haben

See here for the MSDN info http://msdn.microsoft.com/en-us/library/ms190315.aspx

3
hinzugefügt

* Parameter order in the connection string is sometimes important. * The Provider parameter's location can break the recordset cursor after adding a row. We saw this behavior with the SQLOLEDB provider.

Nachdem eine Zeile hinzugefügt wurde, sind die Zeilenfelder nicht verfügbar, sofern der Provider in der Verbindungszeichenfolge nicht als erster Parameter angegeben wurde. Wenn sich der Anbieter an einer beliebigen Stelle in der Verbindungszeichenfolge befindet, mit Ausnahme des ersten Parameters, sind die neu eingefügten Zeilenfelder nicht verfügbar. Als wir den Provider auf den ersten Parameter verschoben haben, erschienen die Zeilenfelder auf magische Weise.

2
hinzugefügt
Sie müssen Ihre Antwort bearbeiten und verbessern. Es ist derzeit laut und nicht als eine anständige Antwort oder sogar ein Versuch
hinzugefügt der Autor James, Quelle
Wahrscheinlich sind viele Benutzer zu dieser Seite gekommen, weil sie keine gültigen Felder zur Identifizierung der gerade hinzugefügten Zeile hatten. Dieses Verhalten, das wir gefunden haben (das Ändern der Reihenfolge der Parameter in der Verbindungszeichenfolge ermöglicht den sofortigen Zugriff auf die neu hinzugefügte Zeile), ist so bizarr, dass ich dachte, es würde in Großbuchstaben erwähnt werden, besonders da es sehr wahrscheinlich den Grund dafür beheben wird, dass Leute das Neue wollen Zeilen-ID und andere Felder dieser Zeile. Indem Sie einfach den Provider als ersten Parameter angeben, verschwindet das Problem.
hinzugefügt der Autor David Guidos, Quelle
Was genau meinst du mit "laut"? Sie müssen Ihre Beschwerde erklären. Es ist so einfach wie es nur sein kann. Wenn Sie die Reihenfolge der Parameter in Ihrer Verbindungszeichenfolge ändern, kann dies Auswirkungen darauf haben, ob Zeilendaten nach einer Einfügung verfügbar sind.
hinzugefügt der Autor David Guidos, Quelle
Können Sie uns sagen, wie dieser Kommentar auf die gestellte Frage reagiert/relevant ist? Ich glaube nicht, dass es caps/bold verdient. Wenn Ihre Antwort als hilfreich erachtet wird, stimmen die Nutzer ab.
hinzugefügt der Autor n__o, Quelle

Sie können eine SELECT-Anweisung an Ihre insert-Anweisung anhängen. Ganzzahl myInt = Einfügen in Tabelle1 (FName) -Werte ('Fred'); Wählen Sie Scope_Identity (); Dies wird einen Wert der Identität zurückgeben, wenn der Scaler ausgeführt wird.

0
hinzugefügt

So verwende ich OUTPUT INSERTED beim Einfügen in eine Tabelle, die ID als Identitätsspalte in SQL Server verwendet:

'myConn is the ADO connection, RS a recordset and ID an integer
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())")
ID=RS(0)
0
hinzugefügt