Comment obtenir la dernière ligne d'identité Inséré lors de l'utilisation au lieu de déclenchement
-
22-10-2019 - |
Question
Quand j'insérer dans les tables à l'aide au lieu de déclencheurs, @@Identity
, IDENT_CURRENT('Table')
et SCOPE_IDENTITY()
return null. Comment puis-je obtenir la dernière identité de ligne insérée?
La solution
Avec un déclencheur INSTEAD_OF cela signifie pas insérer encore eu lieu. Vous ne pouvez pas connaître l'identité car il n'a pas encore été généré. Faufilant la valeur de métadonnées est possible ( DBCC CHECKIDENT
), mais compter sur elle ne fonctionnera pas correctement sous concurrency et d'ailleurs, il requiert des privilèges élevés.
déclencheurs de INSTEAD_OF sont très rarement nécessaires et une odeur grave de code. Etes-vous sûr besoin? Tu ne peux pas faire le travail avec un déclencheur régulier APRÈS?
Autres conseils
Dans votre lieu de détente, vous pouvez certainement obtenir la valeur insérée ... mais pas jusqu'à ce que vous avez effectué l'insert.
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
Résultats:
id
----
1
nettoyage:
DROP TABLE dbo.SmellThis;
En aparté, vous ne devriez jamais, jamais, jamais en utilisant @@IDENTITY
ou IDENT_CURRENT()
de toute façon. Et SCOPE_IDENTITY
devrait être réservé aux situations où vous savez qu'une seule ligne ne peut jamais être inséré. Une idée fausse commune avec des déclencheurs est qu'ils feu par ligne, comme dans d'autres plates-formes, mais dans SQL Server, ils le feu par opération - donc un multi-lignes insert en utilisant VALUES(),(),()
ou INSERT...SELECT
- qui SCOPE_IDENTITY
voulez-vous installerez à votre variable
Problème principal: Trigger et Entity Framework à la fois les travaux d'envergure diffrent. Le problème est que si vous créez une nouvelle valeur de PK dans déclencheur, il est différent portée. Ainsi cette commande renvoie zéro lignes et EF jetteront exception.
La solution est d'ajouter l'instruction SELECT suivante à la fin de votre Trigger:
SELECT * FROM deleted UNION ALL
SELECT * FROM inserted;
à la place de * vous pouvez mentionner tout le nom de colonne comprenant
SELECT IDENT_CURRENT(‘tablename’) AS <IdentityColumnname>