我有两张这样的表:
Table1 Table2
----------------------------------
Table1Id IDENTITY Table2Id
Table2Id NOT NULL SomeStuff
SomeOtherStuff
对它们之间的Table2Id使用外键约束。不用说(但我还是说它)需要在其相关的Table1行之前插入Table2行。加载两个表的过程的性质在批量集合操作中这样做,这意味着我在@temp表中有一大堆Table1和Table2数据,这些数据是使用IDENTITY
列创建的,用于跟踪事物。我目前正在进行这样的插入(为简洁省略了事务和错误处理):
DECLARE @currentTable2Id INT
SET @currentTable2Id = IDENT_CURRENT('dbo.Table2')
INSERT INTO dbo.Table2 WITH (TABLOCKX)
( SomeStuff,
SomeOtherStuff
)
SELECT WhateverStuff,
WhateverElse
FROM @SomeTempTable
ORDER BY SomeTempTableId
INSERT INTO dbo.Table1
( Table2Id )
SELECT @currentTable2Id + SomeTempTableId
FROM @SomeTempTable
ORDER BY SomeTempTableId
这很好用,插入后所有的关系都是合理的。但是,由于TABLOCKX
,我们遇到了人们等待彼此的查询完成的常数情况,无论是这个“加载”查询,还是其他UPDATES和INSERTS(我正在使用{{1}选择)。项目的性质要求加载很多数据,因此有时这个过程可以运行20-30分钟。关于这种表现,我无能为力。相信我,我已经尝试过了。
我无法使用NOLOCK
,因为DBA不允许用户在生产中发出此命令,我认为使用SET IDENTITY_INSERT ON
无论如何都需要IDENTITY_INSERT
。有没有办法在不使用TABLOCKX
的情况下进行此类插入?
答案 0 :(得分:2)
我假设您正在使用tablockx,以防止在进程持续时间内插入表2(从而增加标识值)。试试这个
DECLARE @t TABLE (Table2Id int), @currentTable2Id int
INSERT INTO dbo.Table2
( SomeStuff,
SomeOtherStuff
)
OUTPUT INSERTED.Table2Id into @t
SELECT WhateverStuff,
WhateverElse
FROM @SomeTempTable
ORDER BY SomeTempTableId
SELECT @currentTable2Id = Table2Id FROM @t
INSERT INTO dbo.Table1
( Table2Id )
SELECT @currentTable2Id + SomeTempTableId
FROM @SomeTempTable
ORDER BY SomeTempTableId
DELETE @t
答案 1 :(得分:2)
确保ID
中有@SomeTempTable
字段。在TempID
中创建新列Table2
。向ID
添加行时,将@SomeTempTable
从TempID
插入Table2
。当您插入TempID
以获取自动递增的Table1
时,在联接中使用列Table2ID
。
这样的事情:
alter table Table2 add TempID int
go
declare @SomeTempTable table(ID int identity, WhateverStuff int, WhateverElse int)
insert into @SomeTempTable values(1, 1)
insert into @SomeTempTable values(2, 2)
insert into Table2(SomeStuff, SomeOtherStuff, TempID)
select WhateverStuff, WhateverElse, ID
from @SomeTempTable
insert into Table1(Table2Id)
select Table2ID
from @SomeTempTable as S
inner join Table2 as T2
on S.ID = T2.TempID
go
alter table Table2 drop column TempID
您可以在每次运行之前清除TempID列,而不是添加和删除TempID列,因此以前运行的旧值不会混淆您的连接。