[英]Inserted clause returns 0 when used with triggers
I'm trying to get the last inserted rows Id from an inserts statement on the following table using SQL server 2012 我正在尝试使用SQL Server 2012从下表的插入语句中获取最后插入的行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] [datetime2](7) NULL,
CONSTRAINT [pk_Table] PRIMARY KEY CLUSTERED
(
[TableId] ASC
)
I'm also using an audit triggers on that table that are as follows: 我还在该表上使用如下的审计触发器:
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
I used different approaches, but nothing 'SAFE' seems to work. 我使用了不同的方法,但是“ SAFE”似乎没有任何作用。
Using scope identity returns null 使用范围标识返回null
insert into dbo.[Table](Name) Values('foo')
select SCOPE_IDENTITY()
Using OUTPUT INSERTED always returns 0 for the identity coloumns; 使用OUTPUT INSERTED总是为标识列返回0; although it returns the other inserted values:
尽管它返回其他插入的值:
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
I know of another solution to get the inserted Id from the triggers itself, by executing a dynamic sql command as follows: 我知道通过执行以下动态sql命令从触发器本身获取插入的ID的另一种解决方案:
declare @tmpTable table (id int)
insert @tmpTable (id )
exec sp_executesql N'insert into dbo.[Table](Name) Values(''foo'')'
select id from @tmpTable
I couldn't figure out why in the first 2 cases it is not working; 我不知道为什么在前两个案例中它不起作用。 why the SCOPE_IDENTITY() does not work although the triggers execute in the same transaction?
为什么即使触发器在同一事务中执行,SCOPE_IDENTITY()也不起作用? And also why the INSERTED clause returns 0 for the identity column.
以及为什么INSERTED子句为标识列返回0。
It appears that the following requirements apply to your audit column data: 看来以下要求适用于您的审核列数据:
CreatedBy
, or use SYSTEM_USER
by default. CreatedBy
提供的插入值,或者默认情况下使用SYSTEM_USER
。 GETUTCDATE()
for CreatedDate
. CreatedDate
使用GETUTCDATE()
。 If the INSTEAD OF trigger (rather than an AFTER trigger) is not essential to your requirements, then you can use DEFAULT constraints on your audit columns and an AFTER INSERT trigger to enforce requirement #2. 如果INSTEAD OF触发器(而不是AFTER触发器)对您的要求不是必需的,则可以在审核列上使用DEFAULT约束,并使用AFTER INSERT触发器来强制执行要求2。
CREATE TABLE [dbo].[Table]
(
[TableId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[CreatedBy] [nvarchar](50) NOT NULL CONSTRAINT [DF_Table_CreatedBy] DEFAULT SYSTEM_USER,
[CreatedDate] [datetime2](7) NOT NULL CONSTRAINT [DF_Table_CreatedDate] DEFAULT GETUTCDATE(),
[ModifiedBy] [nvarchar](50) NULL,
[ModifiedDate] [datetime2](7) NULL,
CONSTRAINT [pk_Table] PRIMARY KEY CLUSTERED ([TableId] ASC)
)
GO
CREATE TRIGGER Trigger_Table_AfterInsert ON [dbo].[Table]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
UPDATE [dbo].[Table] SET [CreatedDate]=GETUTCDATE()
FROM [dbo].[Table] AS T
INNER JOIN INSERTED AS I ON I.[TableId]=T.[TableId]
END
GO
Then, both SCOPE_IDENTITY()
and OUTPUT INSERTED techniques to get the new TableId
value work as expected. 然后,
SCOPE_IDENTITY()
和OUTPUT INSERTED技术都可以按预期工作,以获取新的TableId
值。
If the INSTEAD OF trigger is essential to your implementation, then SELECT @@IDENTITY
is an alternative to SCOPE_IDENTITY
. 如果INSTEAD OF触发器是你的执行是必不可少的,那么
SELECT @@IDENTITY
是一种替代SCOPE_IDENTITY
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.