Wenn ich in Tabellen einfügen anstelle von Trigger verwenden, @@Identity
, IDENT_CURRENT('Table')
und SCOPE_IDENTITY()
null zurück. Wie kann ich die letzte Identität der eingefügten Zeile erhalten?
Wenn ich in Tabellen einfügen anstelle von Trigger verwenden, @@Identity
, IDENT_CURRENT('Table')
und SCOPE_IDENTITY()
null zurück. Wie kann ich die letzte Identität der eingefügten Zeile erhalten?
Antworten:
Mit einem INSTEAD_OF-Trigger bedeutet dies, dass noch keine Einfügung erfolgt ist. Sie können die Identität nicht kennen, da sie noch nicht generiert wurde. Das Löschen des Werts aus Metadaten ist möglich ( DBCC CHECKIDENT
), aber wenn Sie sich darauf verlassen, funktioniert dies bei gleichzeitiger Verwendung nicht richtig und erfordert außerdem erhöhte Berechtigungen.
INSTEAD_OF-Trigger sind äußerst selten erforderlich und riechen ernsthaft nach Code. Bist du sicher, dass du es brauchst? Können Sie die Arbeit nicht mit einem regulären AFTER-Trigger erledigen?
Anstelle von Trigger können Sie definitiv den eingefügten Wert erhalten ... aber erst, nachdem Sie das Einfügen durchgeführt haben.
USE tempdb;
GO
CREATE TABLE dbo.SmellThis
(
id INT IDENTITY(1,1),
name VARCHAR(32)
);
GO
CREATE TRIGGER dbo.SmellThis_First
ON dbo.SmellThis
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ids TABLE(id INT);
IF NOT EXISTS
(
SELECT 1 FROM sys.objects AS o
INNER JOIN inserted AS i
ON o.name = i.name
)
INSERT dbo.SmellThis(name)
OUTPUT inserted.id INTO @ids
SELECT name
FROM inserted;
SELECT id FROM @ids;
END
GO
INSERT dbo.SmellThis(name) SELECT 'Remus';
GO
Ergebnisse:
id
----
1
Jetzt aufräumen:
DROP TABLE dbo.SmellThis;
Abgesehen davon sollten Sie niemals @@IDENTITY
oder niemals etwas verwenden IDENT_CURRENT()
. Und SCOPE_IDENTITY
sollte für Situationen reserviert werden, in denen Sie wissen, dass immer nur eine Zeile eingefügt werden kann. Ein häufiges Missverständnis bei Triggern ist, dass sie wie auf anderen Plattformen pro Zeile ausgelöst werden, in SQL Server jedoch pro Operation - also eine mehrzeilige Einfügung mit VALUES(),(),()
oder INSERT...SELECT
- welche SCOPE_IDENTITY
würden Sie für Ihre Variable festlegen?
Hauptproblem: Trigger- und Entity-Framework arbeiten beide in unterschiedlichem Umfang. Das Problem ist, dass wenn Sie im Trigger einen neuen PK-Wert generieren, dieser einen anderen Bereich hat. Somit gibt dieser Befehl null Zeilen zurück und EF löst eine Ausnahme aus.
Die Lösung besteht darin, die folgende SELECT-Anweisung am Ende Ihres Triggers hinzuzufügen:
SELECT * FROM deleted UNION ALL
SELECT * FROM inserted;
Anstelle von * können Sie alle Spaltennamen einschließlich angeben
SELECT IDENT_CURRENT(‘tablename’) AS <IdentityColumnname>
inserted
BeimINSTEAD OF
Auslösen eines Triggers wird jedoch keine Zeile eingefügt .