我正在尝试使用从一个表插入另一个表
DECLARE @IDOffset int;
SELECT @IDOffset = MAX(ISNULL(ID,0)) FROM TargetTable
INSERT INTO TargetTable(ID, FIELD)
SELECT [Increment] + @IDOffset ,FeildValue
FROM SourceTable
WHERE [somecondition]
TargetTable.ID 不是一个标识列,这就是为什么我必须自己找到一种自动递增它的方法。
我知道我可以使用游标,或者创建一个带有标识列和 FieldValue 字段的表变量,填充它,然后在我的insert into...select
,但这效率不高。我尝试使用 ROW_NUMBER 函数来递增,但我确实在 SourceTable 中没有可以使用的合法 ORDER BY 字段,并且希望保留 SourceTable 的原始顺序(如果可能)。
任何人都可以提出任何建议吗?
您可以避免指定显式排序,如下所示:
INSERT dbo.TargetTable (ID, FIELD)
SELECT
Row_Number() OVER (ORDER BY (SELECT 1))
+ Coalesce(
(SELECT Max(ID) FROM dbo.TargetTable WITH (TABLOCKX, HOLDLOCK)),
0
),
FieldValue
FROM dbo.SourceTable
WHERE {somecondition};
但是,请注意,这只是避免指定顺序的一种方法,不保证任何原始数据顺序都将被保留。还有其他因素可能导致结果排序,例如ORDER BY
在外部查询中。为了充分理解这一点,我们必须认识到“未排序(以特定方式)”的概念与“保留原始顺序”(以特定方式排序!)不同。我认为,从纯关系数据库的角度来看,后一个概念不存在, 根据定义(尽管可能有数据库实现违反了这一点,但 SQL Server 不是其中之一)。
计算的原因Max
在查询中添加锁定提示是为了防止由于并发进程在查询执行部分之间使用您计划使用的相同值插入而导致错误。唯一的其他半合理的解决方法是在循环中执行 Max() 和 INSERT 多次,直到成功(距离理想的解决方案还很远)。使用标识列是远远优于。独占锁定整个表对并发性不利,这是轻描淡写的说法。
注:很多人用(SELECT NULL)
绕过“窗口函数的 ORDER BY 子句中不允许使用常量”的限制。出于某种原因,我更喜欢1
over NULL
。你用什么取决于你。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)