0

我在桌子上有一个而不是触发器。触发器工作正常,但我们有一个应用程序,用户可以在其中通过 UI 对表执行批量更新。在这种情况下,select scope_identity 返回 null。当用户通过 UI 执行更新时,我运行 sql profiler 来查看后台发生了什么,我得到了这个:

insert into Table(column1, column2,....)
values (value1, value2,.....)
go
select scope_identity()
go

在这种情况下,内部定义的 scope_identity() 而不是 trigger 返回正确的值,但上述语句中的 scope_identity() 返回 null 并且应用程序此时会抛出错误。我想这是因为插入发生在触发器内部,它不属于上述 scope_identity 的范围。我知道可以通过使用 after trigger 代替 trigger 来解决此问题,但是该表包含 ntext 列,这将阻止我使用 after trigger。将 ntext 列转换为 nvarchar(max) 也不是我的选择。关于如何使 select scope_identity() 返回正确值的任何想法?

提前致谢。

4

1 回答 1

0

好的,我可以重现您的问题并给出解释和解决方案。

use tempdb
go
set ansi_nulls on 
set quoted_identifier on 
go 
create table sampletable (
ix int identity primary key,
column1 nvarchar(50),
column2 nvarchar(50)
)
go
go
      /* First with no trigger - works fine */
insert sampletable(column1, column2)
select 'a', 'b'
select @@identity, scope_identity(), ident_current('sampletable')
select * from sampletable

go
      /* create instead trigger */
create trigger dbo.sampletrigger on sampletable 
instead of insert 
as 
begin 
insert into sampletable(column1, column2) select column1, column2 from inserted 
end
go

      /* Now scope_identity() is null */
insert sampletable(column1, column2)
select 'a', 'b'
select @@identity, scope_identity(), ident_current('sampletable')
select * from sampletable
go
go
go
drop table sampletable

Scope_identity()为空,因为您没有在当前范围内插入具有标识的行。

Scope_identity()是当前批次中插入当前范围的最后一个标识。触发器是一个单独的范围,所以在触发器之外它是空的。无论范围如何,您都需要使用@@identity哪个是批次中插入的最后一个身份。

不能使用ident_current('sampletable')在该特定表上的任何批次和任何会话中插入的最后一个身份,因为这可能会因其他并发用户而导致更改。

于 2012-05-23T09:37:05.170 回答