Quando inserisco in tabelle utilizzando al posto di trigger, @@Identity
, IDENT_CURRENT('Table')
e SCOPE_IDENTITY()
nulla di ritorno. Come posso ottenere l'ultima identità della riga inserita?
Quando inserisco in tabelle utilizzando al posto di trigger, @@Identity
, IDENT_CURRENT('Table')
e SCOPE_IDENTITY()
nulla di ritorno. Come posso ottenere l'ultima identità della riga inserita?
Risposte:
Con un trigger INSTEAD_OF significa che non si è ancora verificato alcun inserimento. Non puoi conoscere l'identità poiché non è stata ancora generata. È possibile sgattaiolare il valore dai metadati ( DBCC CHECKIDENT
) ma fare affidamento su di esso non funzionerà correttamente in concorrenza e inoltre richiede privilegi elevati.
I trigger INSTEAD_OF sono estremamente rari e un odore di codice serio. Sei sicuro di averne bisogno? Non riesci a fare il lavoro con un normale trigger AFTER?
Nel tuo trigger anziché, puoi sicuramente ottenere il valore inserito ... ma non fino a dopo aver eseguito l'inserimento.
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
risultati:
id
----
1
Ora ripulisci:
DROP TABLE dbo.SmellThis;
Per inciso, non dovresti mai, mai, mai usare @@IDENTITY
o IDENT_CURRENT()
comunque. E SCOPE_IDENTITY
dovrebbe essere riservato per le situazioni in cui sai che è possibile inserire solo una riga. Un malinteso comune con i trigger è che si attivano per riga, come in altre piattaforme, ma in SQL Server si attivano per operazione - quindi un inserto multi-riga utilizzando VALUES(),(),()
o INSERT...SELECT
- quale SCOPE_IDENTITY
si imposta sulla variabile?
Problema principale: il framework Trigger ed Entity funzionano entrambi in un ambito diverso. Il problema è che se si genera un nuovo valore PK nel trigger, si tratta di un ambito diverso. Pertanto, questo comando restituisce zero righe e EF genererà un'eccezione.
La soluzione è aggiungere la seguente istruzione SELECT alla fine del trigger:
SELECT * FROM deleted UNION ALL
SELECT * FROM inserted;
al posto di * puoi citare tutto il nome della colonna incluso
SELECT IDENT_CURRENT(‘tablename’) AS <IdentityColumnname>
inserted
stata inserita alcuna riga quando siINSTEAD OF
attiva un trigger.