我的应用程序将一些数据插入表中。
insert into this_Table (id, value, value)
然后我创建了一个触发器,它使用主键执行简单插入到另一个表中。
insert into temp_wc_triggertest values ('test', GETDATE())
我的问题是,应用程序尝试从第一个插入中查找scope_identity
。但是,它会被触发器覆盖,触发器会将范围标识更改为temp_wc_triggertest
的主键。
如何阻止触发器覆盖scope_identity
?
我意识到这里没有太多代码需要帮助,这通常被归类为一个不好的问题,但我目前无权访问完整的应用程序代码,所以我希望这是一个可以回答的问题。是
这是在SQL Server 2008 R2上
编辑:我查看了代码,确实使用了scope_identity
答案 0 :(得分:2)
您的客户肯定使用@@IDENTITY而不是SCOPY_IDENTITY()
这是一个SQL小提琴,其中包含一些可以测试的代码。
MS SQL Server 2008架构设置:
create table T1(ID int identity(1,1));
create table T2(ID int identity(1000, 1));
go
create trigger tr_T1 on T1 for insert
as
insert into T2 default values;
<强>查询强>:
insert into T1 default values
select @@identity as "@@identity",
scope_identity() as "scope_identity()"
<强> Results 强>:
| @@IDENTITY | SCOPE_IDENTITY() |
---------------------------------
| 1000 | 1 |
答案 1 :(得分:2)
如果您正确使用SCOPE_IDENTIY,您可能还会遇到已知错误 - http://connect.microsoft.com/SQLServer/feedback/details/328811
MS已将其永久修复为2012年,并且已针对2008和2008R2提供补丁。
答案 2 :(得分:2)
它覆盖范围标识的原因尚不清楚,它可能与提到的错误有关。但是找到了修复:
临时表创建了“temp_wc”
然后在触发器的末尾,为该表启用了标识插入,并且在触发器触发后我们想要保留的ID完成插入。可以将此方法视为重写覆盖的范围标识。
SET IDENTITY_INSERT ON
INSERT INTO temp_wc VALUES (@ID, 'fix scope identity error')
答案 3 :(得分:0)
使用SELECT IDENT_CURRENT(‘tablename’)
“它返回表中生成的最后一个IDENTITY值,无论创建该值的连接如何,也不管产生该值的语句的范围如何。”
有关详细信息,请参阅此链接。
答案 4 :(得分:0)
这可能会在将来帮助任何人解决此问题:
您可能需要修补SQL Server,因为SCOPE_IDENTITY
应该返回实际接收主插入而不是SQL触发器插入语句的表上的插入ID。
从SQL Server 2017的Microsoft文档中获取(如果链接断开):
备注SCOPE_IDENTITY,IDENT_CURRENT和@@ IDENTITY相似 函数,因为它们返回插入到标识中的值 列。
IDENT_CURRENT不受范围和会话的限制;它仅限于 指定表。 IDENT_CURRENT返回为生成的值 任何会话和任何范围的特定表。有关更多信息,请参见 IDENT_CURRENT(Transact-SQL)。
SCOPE_IDENTITY和@@ IDENTITY返回的最后一个标识值是 在当前会话的任何表中生成。但是,SCOPE_IDENTITY 返回仅在当前范围内插入的值; @@ IDENTITY为 不限于特定范围。
例如,有两个表T1和T2,并且INSERT触发器是 在T1上定义。当在T1中插入一行时,触发器将触发并 在T2中插入一行。此方案说明了两个范围:插入 在T1上,通过触发器在T2上插入。
假定T1和T2都具有标识列@@ IDENTITY和 SCOPE_IDENTITY在INSERT的末尾返回不同的值 关于T1的声明。 @@ IDENTITY返回最后一个身份列值 插入当前会话中的任何作用域。这就是价值 插入T2。 SCOPE_IDENTITY()返回插入的IDENTITY值 在T1中。这是同一作用域中发生的最后一次插入。的 如果该函数是SCOPE_IDENTITY()函数,则返回null值 在任何插入身份列的INSERT语句出现之前调用 范围。
失败的语句和事务可以更改当前身份 一个表并在标识列值中创建空白。身份 即使试图进行的交易,价值也不会回滚 将值插入表中未提交。例如,如果 由于违反了IGNORE_DUP_KEY,INSERT语句失败, 该表的当前标识值仍会增加。
此处的另一个链接:
http://www.sqlbadpractices.com/how-not-to-retrieve-identity-value/
此代码的问题是您可能无法检索到身份 您插入的值。例如,如果 在另一个表上执行插入操作的表,您将获得最后一个 创建身份值。即使您从未创建任何触发器,也可能 由于SQL Server创建了复制的表,因此得到的结果与复制的表有偏差 自己的复制触发器。