我尝试使用SQL Server 2012从下表中的insert语句中获取最后插入的行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
)
我还在该表上使用了如下审计触发器:
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
我使用了不同的方法,但没有什么&#39;安全&#39;似乎工作。
使用范围标识返回null
insert into dbo.[Table](Name) Values('foo')
select SCOPE_IDENTITY()
使用OUTPUT INSERTED始终为身份颜色返回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
我知道通过执行动态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
我无法弄清楚为什么在前两种情况下它不起作用;虽然触发器在同一个事务中执行,但为什么SCOPE_IDENTITY()不起作用?以及为什么INSERTED子句为标识列返回0。
答案 0 :(得分:1)
以下要求似乎适用于您的审核列数据:
CreatedBy
提供的插入值,或默认情况下使用SYSTEM_USER
。GETUTCDATE()
用于CreatedDate
。如果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
然后,SCOPE_IDENTITY()
和OUTPUT INSERTED技术都可以使新的TableId
值按预期工作。
如果INSTEAD OF触发器 对您的实施至关重要,那么SELECT @@IDENTITY
可替代SCOPE_IDENTITY
。