简体   繁体   English

与触发器一起使用时,插入子句返回0

[英]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: 看来以下要求适用于您的审核列数据:

  1. Use the insert value supplied for CreatedBy , or use SYSTEM_USER by default. 使用为CreatedBy提供的插入值,或者默认情况下使用SYSTEM_USER
  2. Always use 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.

相关问题 当没有使用“order by”子句时,Oracle SQL以任意方式返回行 - Oracle SQL returns rows in arbitrary fashion when no “order by” clause is used SQL触发器,在插入/更新/删除项目时调用存储的proc - SQL triggers, invoke stored proc when an item is inserted/updated/deleted 在触发器中使用If_Else时出错 - Error when If_Else used in triggers 使用触发器更新SQL中的记录时,在FileMaker中添加记录时,不能将OUTPUT子句与INTO子句一起使用 - Cannot use OUTPUT clause with INTO clause when using Triggers to update records in SQL, when adding a record in FileMaker 输出子句VS触发器 - output clause VS triggers OR括号中使用的运算符与where子句一起返回不同的结果。 - OR Operator used in parenthesis along with where clause returns different result. SQL - 何时使用空的OVER子句? - SQL - When would an empty OVER clause be used? 使用whereAutogenerate时可以组合where子句吗? - is possible to combine where clause when whereAutogenerate is used? 与“转换”函数一起使用时,Where 子句失败 - Where clause fails when used with a 'convert' function 当在WHERE子句中使用时,MySQL是否缓存了子查询? - Are subqueries cached by MySQL when used in a WHERE clause?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM