Sql 与触发器一起使用时,Inserted子句返回0
我试图使用SQL server 2012从下表的inserts语句中获取最后插入的行IdSql 与触发器一起使用时,Inserted子句返回0,sql,sql-server,Sql,Sql Server,我试图使用SQL server 2012从下表的inserts语句中获取最后插入的行Id [dbo].[Table]( [TableId] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](50) NULL, [CreatedBy] [nvarchar](50) NULL, [CreatedDate] [datetime2](7) NOT NULL, [ModifiedBy] [nvarchar](50) NULL, [ModifiedDate] [
[dbo].[Table](
[TableId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[CreatedBy] [nvarchar](50) NULL,
[CreatedDate] [datetime2](7) NOT NULL,
[ModifiedBy] [nvarchar](50) NULL,
[ModifiedDate] [datetime2](7) NULL,
CONSTRAINT [pk_Table] PRIMARY KEY CLUSTERED
(
[TableId] ASC
)
我还在该表上使用审计触发器,如下所示:
trigger [dbo].[trigger_Table_auditColumnAutoInsert]
on [dbo].[Table]
instead of insert
/**************************************************************
* INSTEAD OF trigger on table [dbo].[Table] responsible
for automatically inserting audit column data
**************************************************************/
as
begin
set nocount on
declare @currentTime datetime2
set @currentTime = GETUTCDATE()
insert into [dbo].[Table]
(
Name,
CreatedBy,
CreatedDate,
ModifiedBy,
ModifiedDate
)
select
Name,
ISNULL(CreatedBy, system_user),
@currentTime,
NULL,
NULL
from inserted
select SCOPE_IDENTITY() as [TableId]
goto EOP -- end of procedure
ErrorHandler:
if (@@trancount <> 0) rollback tran
EOP:
end
declare @tmpTable table (id int)
insert @tmpTable (id )
exec sp_executesql N'insert into dbo.[Table](Name) Values(''foo'')'
select id from @tmpTable
使用插入的输出总是为标识列返回0;尽管它返回其他插入的值:
declare @tmpTable table
(
TableId int,
Name nvarchar (50)
)
INSERT INTO [dbo].[Table]([Name])
output inserted.TableId, inserted.Name into @tmpTable
VALUES('foo')
select * from @tmpTable
TableId Name
0 foo
我知道另一种从触发器本身获取插入Id的解决方案,方法是执行动态sql命令,如下所示:
trigger [dbo].[trigger_Table_auditColumnAutoInsert]
on [dbo].[Table]
instead of insert
/**************************************************************
* INSTEAD OF trigger on table [dbo].[Table] responsible
for automatically inserting audit column data
**************************************************************/
as
begin
set nocount on
declare @currentTime datetime2
set @currentTime = GETUTCDATE()
insert into [dbo].[Table]
(
Name,
CreatedBy,
CreatedDate,
ModifiedBy,
ModifiedDate
)
select
Name,
ISNULL(CreatedBy, system_user),
@currentTime,
NULL,
NULL
from inserted
select SCOPE_IDENTITY() as [TableId]
goto EOP -- end of procedure
ErrorHandler:
if (@@trancount <> 0) rollback tran
EOP:
end
declare @tmpTable table (id int)
insert @tmpTable (id )
exec sp_executesql N'insert into dbo.[Table](Name) Values(''foo'')'
select id from @tmpTable
我不明白为什么在前两个案例中它不起作用;为什么虽然触发器在同一事务中执行,但SCOPE_IDENTITY()不起作用?以及INSERTED子句为标识列返回0的原因。以下要求似乎适用于审核列数据:
CreatedBy
提供的插入值,或使用SYSTEM\u USER
CreatedDate
,始终使用GETUTCDATE()
SCOPE\u IDENTITY()
和输出插入技术来获得新的TableId
值
如果INSTEAD OF触发器对于您的实现是必不可少的,那么
SELECT@@IDENTITY
是SCOPE\u IDENTITY
的替代方法,如果您尝试的是小猪而不是跳跳虎?很抱歉我忍不住对你的问题中的拼写错误感兴趣。。。我希望温和的幽默不会在SO中受到反对……但是@@IDENTITY不是一个安全的选项。我没有一个现成的解释来解释为什么SCOPE_IDENTITY()不能与INSTEAD OF触发器一起工作。我尝试了您的示例,得到了与您相同的结果。@user908723-无论是@@IDENTITY
还是SCOPE\u IDENTITY
在触发器中都将是一个不正确的概念,因为触发器是针对语句而不是针对每一行触发的-对于多行插入
,已生成多个标识值,但@@identity
和SCOPE\u identity
都只返回一个值。