Was ist der beste Weg, um aus IDENTITY
der eingefügten Zeile zu kommen?
Ich kenne @@IDENTITY
und IDENT_CURRENT
und SCOPE_IDENTITY
verstehe aber nicht die Vor- und Nachteile, die mit jedem verbunden sind.
Kann jemand bitte die Unterschiede erklären und wann ich sie jeweils verwenden sollte?
sql
sql-server
tsql
Oded
quelle
quelle
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)
oder ältere Methode:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
Sie können sie mit ExecuteScalar () in c # abrufen.OUTPUT
Klausel in SQL Server.Antworten:
@@IDENTITY
Gibt den letzten Identitätswert zurück, der für eine Tabelle in der aktuellen Sitzung in allen Bereichen generiert wurde. Sie müssen hier vorsichtig sein , da es sich um Bereiche handelt. Sie könnten anstelle Ihrer aktuellen Anweisung einen Wert von einem Trigger erhalten.SCOPE_IDENTITY()
Gibt den letzten Identitätswert zurück, der für eine Tabelle in der aktuellen Sitzung und den aktuellen Bereich generiert wurde. Im Allgemeinen, was Sie verwenden möchten .IDENT_CURRENT('tableName')
Gibt den letzten Identitätswert zurück, der für eine bestimmte Tabelle in einer Sitzung und einem Bereich generiert wurde. Auf diese Weise können Sie angeben, aus welcher Tabelle der Wert stammen soll, falls die beiden oben genannten nicht ganz Ihren Anforderungen entsprechen ( sehr selten ). Wie @ Guy Starbuck bereits sagte: "Sie können dies verwenden, wenn Sie den aktuellen IDENTITY-Wert für eine Tabelle abrufen möchten, in die Sie keinen Datensatz eingefügt haben."Mit der
OUTPUT
Klausel derINSERT
Anweisung können Sie auf jede Zeile zugreifen, die über diese Anweisung eingefügt wurde. Da es auf die spezifische Anweisung beschränkt ist, ist es einfacher als die anderen oben genannten Funktionen. Es ist jedoch etwas ausführlicher (Sie müssen es in eine Tabellenvariable / temporäre Tabelle einfügen und diese dann abfragen) und liefert Ergebnisse auch in einem Fehlerszenario, in dem die Anweisung zurückgesetzt wird. Wenn Ihre Abfrage jedoch einen Plan für die parallele Ausführung verwendet, ist dies die einzige garantierte Methode zum Abrufen der Identität (ohne die Parallelität zu deaktivieren). Es wird jedoch ausgeführt , bevor Trigger und kann nicht zurück Trigger generierten Werte verwendet werden.quelle
output
Sie keine temporäre Tabelle erstellen, um die Ergebnisse zu speichern und abzufragen. Lassen Sie einfach deninto
Teil der Ausgabeklausel weg und er gibt sie an eine Ergebnismenge aus.OUTPUT
ist die "beste", solange Sie keine Trigger verwenden und Fehler behandeln, aberSCOPE_IDENTITY
die einfachste und sehr selten auftretende ProblemeIch glaube, die sicherste und genaueste Methode zum Abrufen der eingefügten ID wäre die Verwendung der Ausgabeklausel.
zum Beispiel (entnommen aus dem folgenden MSDN- Artikel)
quelle
OUTPUT
in SQL Server 2005 , es sieht also so aus, als ob nur SQL Server 2000 und früher ohne diese Seite sindIch sage das Gleiche wie die anderen, also haben alle Recht, ich versuche nur, es klarer zu machen.
@@IDENTITY
Gibt die ID des letzten Objekts zurück, das von der Verbindung Ihres Clients zur Datenbank eingefügt wurde.Meistens funktioniert dies einwandfrei, aber manchmal wird ein Trigger eine neue Zeile einfügen, von der Sie nichts wissen, und Sie erhalten die ID aus dieser neuen Zeile anstelle der gewünschten
SCOPE_IDENTITY()
löst dieses Problem. Es gibt die ID des letzten Objekts zurück, das Sie in den SQL-Code eingefügt haben, den Sie an die Datenbank gesendet haben . Wenn Trigger zusätzliche Zeilen erstellen, wird nicht der falsche Wert zurückgegeben. HurraIDENT_CURRENT
Gibt die letzte ID zurück, die von jemandem eingefügt wurde. Wenn eine andere App zu einem ungünstigen Zeitpunkt eine weitere Zeile einfügt, erhalten Sie die ID dieser Zeile anstelle Ihrer.Wenn Sie auf Nummer sicher gehen möchten, verwenden Sie immer
SCOPE_IDENTITY()
. Wenn Sie dabei bleiben@@IDENTITY
und jemand beschließt, später einen Auslöser hinzuzufügen, wird Ihr gesamter Code beschädigt.quelle
Der beste (sprich: sicherste) Weg, um die Identität einer neu eingefügten Zeile zu ermitteln, ist die Verwendung der folgenden
output
Klausel:quelle
scope_identity()
) ohnehin parallele Pläne erhalten. Und dieser Fehler wurde mehr als ein Jahr vor dieser Antwort behoben.output
stattscope_identity()
. Ich habe die FUD über Clustering in der Antwort entfernt.Hinzufügen
dann bis zum Ende Ihrer SQL-Anweisung einfügen
wird es abrufen.
quelle
Wenn Sie Entity Framework verwenden, wird die
OUTPUT
Technik intern verwendet , um den neu eingefügten ID-Wert zurückzugebenDie Ausgabeergebnisse werden in einer temporären Tabellenvariablen gespeichert, wieder mit der Tabelle verknüpft und geben den Zeilenwert aus der Tabelle zurück.
Hinweis: Ich habe keine Ahnung, warum EF die kurzlebige Tabelle wieder mit der realen Tabelle verbindet (unter welchen Umständen würden die beiden nicht übereinstimmen).
Aber genau das macht EF.
Diese Technik (
OUTPUT
) ist nur unter SQL Server 2008 oder neuer verfügbar.Bearbeiten - Der Grund für den Join
Der Grund dafür, dass Entity Framework wieder mit der ursprünglichen Tabelle verknüpft wird, anstatt nur die
OUTPUT
Werte zu verwenden, liegt darin, dass EF diese Technik auch verwendet, um dierowversion
einer neu eingefügten Zeile abzurufen.Sie können optimistische Parallelität in Ihren Entity-Framework-Modellen verwenden, indem Sie das folgende
Timestamp
Attribut verwenden: 🕗Wenn Sie dies tun, benötigt Entity Framework die
rowversion
der neu eingefügten Zeile:Und um diese abzurufen
Timetsamp
Sie können nicht eine verwendenOUTPUT
Klausel.Das liegt daran, dass wenn Sie einen Auslöser auf dem Tisch haben, jeder, den
Timestamp
Sie ausgeben, falsch ist:Der zurückgegebene Zeitstempel ist niemals korrekt, wenn Sie einen Auslöser auf dem Tisch haben. Sie müssen also eine separate verwenden
SELECT
.Und selbst wenn Sie bereit wären, die falsche Zeilenversion zu erleiden, besteht der andere Grund für die Durchführung einer separaten Version darin,
SELECT
dass Sierowversion
eine Variable nicht in eine Tabellenvariable ausgeben können:Der dritte Grund dafür ist die Symmetrie. Wenn eine Durchführung
UPDATE
mit einem Trigger auf einem Tisch, man kann nicht eine verwendenOUTPUT
Klausel. Der Versuch,UPDATE
mit einem zu tun,OUTPUT
wird nicht unterstützt und gibt einen Fehler aus:Der einzige Weg, dies zu tun, ist eine Folgeerklärung
SELECT
:quelle
TurboEncabulators
:)MSDN
quelle
@@ IDENTITY ist die letzte Identität, die mit der aktuellen SQL-Verbindung eingefügt wurde. Dies ist ein guter Wert, um von einer gespeicherten Prozedur zum Einfügen zurückzukehren, bei der nur die Identität für Ihren neuen Datensatz eingefügt werden muss, und es ist egal, ob danach weitere Zeilen hinzugefügt wurden.
SCOPE_IDENTITY ist die letzte Identität, die mit der aktuellen SQL-Verbindung und im aktuellen Bereich eingefügt wurde. Wenn also nach dem Einfügen eine zweite IDENTITY basierend auf einem Trigger eingefügt wurde, wird diese nicht in SCOPE_IDENTITY angezeigt, sondern nur in der von Ihnen durchgeführten Einfügung . Ehrlich gesagt hatte ich nie einen Grund, dies zu nutzen.
IDENT_CURRENT (Tabellenname) ist die zuletzt eingefügte Identität, unabhängig von Verbindung oder Bereich. Sie können dies verwenden, wenn Sie den aktuellen IDENTITY-Wert für eine Tabelle abrufen möchten, in die Sie keinen Datensatz eingefügt haben.
quelle
Ich kann nicht mit anderen Versionen von SQL Server sprechen, aber 2012 funktioniert die direkte Ausgabe einwandfrei. Sie müssen sich nicht um einen temporären Tisch kümmern.
Diese Technik funktioniert übrigens auch beim Einfügen mehrerer Zeilen.
Ausgabe
quelle
OUTPUT
. Wenn Sie die temporäre Tabelle nicht benötigen, ist Ihre Abfrage viel einfacher.IMMER Verwendung scope_identity (), dann ist es nie eine Notwendigkeit für irgendetwas anderes.
quelle
Erstellen Sie ein
uuid
und fügen Sie es auch in eine Spalte ein. Dann können Sie Ihre Zeile leicht mit der UUID identifizieren. Dies ist die einzige 100% funktionierende Lösung, die Sie implementieren können. Alle anderen Lösungen sind zu kompliziert oder funktionieren nicht in denselben Randfällen. Z.B:1) Zeile erstellen
2) Erstellen Sie eine Zeile
quelle
uuid
in der Datenbank zu erstellen . So wird die Zeile schneller gefunden.https://www.npmjs.com/package/uuid
.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()
Eine andere Möglichkeit, die Identität der von Ihnen eingefügten Zeilen zu gewährleisten, besteht darin, die Identitätswerte anzugeben und das
SET IDENTITY_INSERT ON
und dann zu verwendenOFF
. Dies garantiert, dass Sie genau wissen, was die Identitätswerte sind! Solange die Werte nicht verwendet werden, können Sie diese Werte in die Identitätsspalte einfügen.Dies kann eine sehr nützliche Technik sein, wenn Sie Daten aus einer anderen Quelle laden oder Daten aus zwei Datenbanken usw. zusammenführen.
quelle
Obwohl dies ein älterer Thread ist, gibt es eine neuere Möglichkeit, um einige der Fallstricke der IDENTITY-Spalte in älteren Versionen von SQL Server zu vermeiden, z. B. Lücken in den Identitätswerten nach dem Neustart des Servers . Sequenzen sind in SQL Server 2016 und Forward verfügbar. Die neuere Methode besteht darin, ein SEQUENCE-Objekt mit TSQL zu erstellen. Auf diese Weise können Sie in SQL Server ein eigenes numerisches Sequenzobjekt erstellen und steuern, wie es inkrementiert wird.
Hier ist ein Beispiel:
Dann würden Sie in TSQL Folgendes tun, um die nächste Sequenz-ID zu erhalten:
Hier sind die Links zu CREATE SEQUENCE und NEXT VALUE FOR
quelle
Nach Ihrer Einfügeanweisung müssen Sie diese hinzufügen. Und stellen Sie sicher, dass der Tabellenname, in den die Daten eingefügt werden, angezeigt wird. Sie erhalten die aktuelle Zeile, in der die Zeile gerade von Ihrer Einfügeanweisung betroffen ist.
quelle