Welche Option ist die beste, um den Identitätswert zu erhalten, den ich gerade über eine Einfügung generiert habe? Welche Auswirkungen haben diese Aussagen auf die Leistung?
SCOPE_IDENTITY()
- Aggregatfunktion
MAX()
- SELECT
TOP 1
IdentityColumn FROM TableNameORDER BY IdentityColumn DESC
Antworten:
Verwenden
SCOPE_IDENTITY()
Sie diese Option, wenn Sie eine einzelne Zeile einfügen und die generierte ID abrufen möchten.Ergebnis:
Verwenden Sie die
OUTPUT
Klausel , wenn Sie mehrere Zeilen und Bedarf abzurufen , die einfügen Satz von IDs , die erzeugt wurden.Ergebnis:
Abgesehen von der Leistung sind dies die einzigen, die in der Standardisolationsstufe und / oder bei mehreren Benutzern garantiert korrekt sind. Selbst wenn Sie den Korrektheitsaspekt ignorieren,
SCOPE_IDENTITY()
speichert SQL Server den eingefügten Wert im Arbeitsspeicher. Dies ist natürlich schneller, als Ihre eigene isolierte Abfrage für die Tabelle oder für Systemtabellen auszuführen.Das Ignorieren des Korrektheitsaspekts bedeutet, dem Postboten mitzuteilen, dass er gute Arbeit bei der Zustellung der heutigen Post geleistet hat. Er beendete seine Route 10 Minuten schneller als seine durchschnittliche Zeit.
Sie nicht eine der folgenden Bedingungen verwendet werden :
@@IDENTITY
- Da dies nicht in allen Szenarien verwendet werden kann, z. B. wenn eine Tabelle mit einer Identitätsspalte einen Trigger hat, der auch in eine andere Tabelle mit einer eigenen Identitätsspalte eingefügt wird, erhalten Sie den falschen Wert zurück.IDENT_CURRENT()
- Ich gehe hier ausführlich darauf ein , und die Kommentare sind ebenfalls hilfreich, aber im Grunde genommen werden Sie bei gleichzeitiger Verwendung häufig die falsche Antwort erhalten.MAX()
oderTOP 1
- Sie müssten die beiden Anweisungen mit serialisierbarer Isolation schützen, um sicherzustellen, dassMAX()
sie nicht von jemand anderem stammen. Dies ist viel teurer als nur die VerwendungSCOPE_IDENTITY()
.Diese Funktionen schlagen auch immer dann fehl, wenn Sie zwei oder mehr Zeilen einfügen und alle generierten Identitätswerte benötigen - Ihre einzige Option ist die
OUTPUT
Klausel.quelle
Abgesehen von der Leistung haben sie alle unterschiedliche Bedeutungen.
SCOPE_IDENTITY()
Gibt den letzten Identitätswert an, der direkt im aktuellen Bereich in eine Tabelle eingefügt wurde (Bereich = Batch, gespeicherte Prozedur usw., jedoch nicht beispielsweise in einem Trigger, der vom aktuellen Bereich ausgelöst wurde).IDENT_CURRENT()
gibt Ihnen den letzten Identitätswert , der von einem Benutzer aus einem beliebigen Bereich in eine bestimmte Tabelle eingefügt wurde .@@IDENTITY
Gibt den letzten Identitätswert an, der von der letzten INSERT-Anweisung für die aktuelle Verbindung generiert wurde, unabhängig von Tabelle oder Bereich. (Randnotiz: Access verwendet diese Funktion und hat daher einige Probleme mit Triggern, die Werte in Tabellen mit Identitätsspalten einfügen.)Die Verwendung von
MAX()
oderTOP 1
kann zu völlig falschen Ergebnissen führen, wenn die Tabelle einen negativen Identitätsschritt aufweist oder Zeilen mitSET IDENTITY_INSERT
im Spiel eingefügt wurden . Hier ist ein Skript, das all dies demonstriert:Zusammenfassung: Halten Sie sich an
SCOPE_IDENTITY()
,IDENT_CURRENT()
oder@@IDENTITY
und vergewissern Sie sich, dass Sie diejenige verwenden, die das zurückgibt, was Sie tatsächlich benötigen.quelle
IDENT_CURRENT()
und@@IDENTITY
wenn Ihr eigenes Skript zeigt, dass es falsche Ergebnisse ausgibt?IDENT_CURRENT()
zurückgibt. MAX () gibt nie den richtigen Wert über die erste Zeile hinaus zurück, da id rückwärts zählt und mitIDENTITY_INSERT
on 9005 kein generierter Identitätswert ist und daher nicht von reflektiert wirdIDENT_CURRENT()
. Aber es kann "falsche" Ergebnisse zurückgeben, wenn Sie wirklich hinter dem her sind, wasSCOPE_IDENTITY()
zurückkommt. Wählen Sie das richtige Werkzeug für den Job.@@IDENTITY
fast nie der ideale Weg ist, um generierte Identitätswerte zu erhalten. Der wichtigste Punkt ist, dassMAX()
oderTOP 1
wie eine weniger zuverlässige Version vonIDENT_CURRENT()
, die eine perfekte Funktion ist, wenn Sie verstehen, was es tut. Könnte für Wartungsarbeiten oder ähnliches nützlich sein.