meh*_*tfi 8 trigger sql-server-2008 sql-server t-sql identity
当我插入表使用INSTEAD OF触发器,@@Identity,IDENT_CURRENT('Table')并SCOPE_IDENTITY()返回null。如何获取插入行的最后一个标识?
Aar*_*and 12
在你的而不是触发器中,你绝对可以获得插入的值......但直到你执行插入之后。
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
Run Code Online (Sandbox Code Playgroud)
结果:
id
----
1
Run Code Online (Sandbox Code Playgroud)
现在清理:
DROP TABLE dbo.SmellThis;
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您永远不应该使用@@IDENTITY或IDENT_CURRENT()无论如何。并且SCOPE_IDENTITY应该保留用于您知道只能插入一行的情况。触发器的一个常见误解是它们按行触发,就像在其他平台中一样,但在 SQL Server 中,它们按操作触发 - 所以使用VALUES(),(),()or的多行插入INSERT...SELECT-SCOPE_IDENTITY您会为变量设置哪个?
使用 INSTEAD_OF 触发器意味着尚未发生插入。您无法知道身份,因为它尚未生成。从元数据中窃取值是可能的 ( DBCC CHECKIDENT) 但依赖它在并发下无法正常工作,此外还需要提升权限。
INSTEAD_OF 触发器极少需要,而且代码味道很重。你确定需要吗?您不能使用常规的 AFTER 触发器来完成这项工作吗?