The*_*Sky 6 sql-server identity insert scope-identity
我有一个存储过程,除了其他功能之外,还有一些循环内不同表中的插入.请参阅以下示例以更清楚地了解:
INSERT INTO T1 VALUES ('something')
SET @MyID = Scope_Identity()
... some stuff go here
INSERT INTO T2 VALUES (@MyID, 'something else')
... The rest of the procedure
Run Code Online (Sandbox Code Playgroud)
这两个表(T1和T2)在每个表中都有一个IDENTITY(1,1)列,我们称之为ID1和ID2; 但是,在我们的生产数据库(非常繁忙的数据库)中运行该程序并在每个表中有超过6250条记录后,我注意到ID1与ID2不匹配的一个事件!虽然通常对于插入T1中的每个记录,但是在T2中插入了记录,并且两者中的标识列一致地递增.
"错误的"记录是这样的:
ID1 Col1
---- ---------
4709 data-4709
4710 data-4710
ID2 ID1 Col1
---- ---- ---------
4709 4710 data-4710
4710 4709 data-4709
Run Code Online (Sandbox Code Playgroud)
注意第二个表中的"倒"ID1.
在操作中对SQL Server知之甚少,我已经提出了以下"理论",也许有人可以纠正我.
我认为因为循环比物理写入表更快,和/或可能延迟写入过程的其他事情,记录被缓冲.在写它们的时候,它们没有特别的顺序写.
如果没有,那是否可能,如何解释上述情况?
如果是,那么我还有另一个问题要提出来.如果第一个插入(来自上面的代码)被延迟怎么办?这是不是意味着我不会将正确的IDENTITY插入第二个表?如果答案也是肯定的,那么我该怎样做才能确保两个表中的插入将按正确的IDENTITY顺序进行?
我感谢任何有助于我理解这一点的评论和信息.
提前致谢.
您无法依靠 IDENTITY 来解决第二个表的问题。如果您关心该行生成的主键值,则应该自行生成。
IDENTITY 是一种说法,“我不想自己生成密钥,只需为我生成密钥,并且在需要时我会询问生成的值”。
这里可能发生的情况是两个线程同时插入行,但它们都尚未提交,因此您会遇到以下情况:
Thread 1 Thread 2
get id for table 1 = 4709
get id for table 1 = 4710
insert row for table 1
insert row for table 1
get id for table 2 = 4709
get id for table 2 = 4710
insert row for table 2
insert row for table 1
Run Code Online (Sandbox Code Playgroud)
您有两种方法可以解决您的问题:
SET IDENTITY_INSERT ON允许您为其提供密钥,同时保留 IDENTITY 设置然而,在这种情况下,我会使用方法 nbr。1. 方法编号。2 通常在将数据导入到空表时使用。您不希望数据库自动生成您稍后想要使用的 ID 的风险(因为它来自第一个表),因此您应该禁用第二个表的主键上的 IDENTITY 设置。
或者您可以尝试完全避免依赖该表的键,因为您有外键引用,您真的需要键值相同吗?
| 归档时间: |
|
| 查看次数: |
1755 次 |
| 最近记录: |