【问题标题】:How to prevent database trigger updating @@identity after Insert如何防止数据库触发器在插入后更新@@identity
【发布时间】:2020-11-30 23:42:07
【问题描述】:

我正在向现有数据库表添加一个触发器,该表由我未编写代码的应用程序使用,并且无法更改其中的代码。

我想在INSERT 上将TableA 中的一些信息插入TableBTableA

  1. 应用程序运行INSERT INTO TableA @@identity
  2. TableA 上运行的ON INSERT 触发器,然后将数据插入TableB @@identity
  3. 应用程序读取@@identity TableB 而不是来自TableA 应用程序所期望的

有什么方法可以不更新触发器内的@@identity

【问题讨论】:

  • 没有办法阻止这种情况发生。这是你永远不应该使用@@identity 的一个重要原因。
  • 是的,我知道 :) 第三方应用程序!
  • 一个非常非常(不,非常严重非常)丑陋的解决方法:在导致@@identity 的触发器结束时(进入某个临时表)发出INSERT设置为所需的值。或者,也许更简洁但更多的工作,考虑一个 INSTEAD OF 触发器反转 INSERTs 的顺序,以便实际的最后完成。
  • “第 3 方应用程序”通常意味着法律不允许您修改架构。添加触发器就是这样的修改 - 小心!

标签: sql-server triggers


【解决方案1】:

....因为@@identity 没有作用域,您可以创建自己的作用域,该作用域在触发器末尾带有@@identity 值

create table tableA(idA int identity(100, 1), colA int)
go

create table tableB(idB int identity(1000, 1), colB int)
go

create trigger triggerA on tableA
for insert
as
begin

    if not exists(select * from inserted)
    begin
        return;
    end

    declare @tableA@@identity int = @@identity;

    select @@identity as [@@identity_triggerA_in];

    --add rows to tableB
    insert into tableB(colB)
    select object_id
    from sys.all_objects

    select @@identity as [@@identity_after_insert_in_tableB];


    if @tableA@@identity is not null
    begin
        declare @sql varchar(100) = concat('create table #t(id int identity(', @tableA@@identity, ',1)); insert into #t default values');
        exec (@sql);
    end

    select @@identity as [@@identity_triggerA_out];

end
go  

insert into tableA(colA) values (10);
select @@identity;

go

insert into tableA(colA)
select top (200) 1
from sys.all_objects;
select @@identity;
go


insert into tableA(colA)
select 1
where 1=2;

select @@identity;

go

drop table tableA;
go
drop table tableB;
go

【讨论】:

  • 感谢@lptr,不理想,但确实有效!
猜你喜欢
  • 2021-04-05
  • 2017-04-26
  • 1970-01-01
  • 2021-03-08
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 2016-10-13
相关资源
最近更新 更多