我正在尝试使用INSERT将一组记录(我将其称为 tblSource )插入到另一个表( tblDestination )中INTO .. SELECT查询,但我必须手动增加我插入 tblDestination 的键值,而不是仅将其设置为IDENTITY,因为 tblDestination 使用复合键。所以我有一个从SELECT内部运行的函数,它找到 tblDestination 的当前最大键值,将其递增1,然后返回该值。
该功能如下所示:
ALTER FUNCTION [dbo].[GetNextStringID] ()
RETURNS INT AS
BEGIN
DECLARE @nextstringid INT
SELECT @nextstringid = MAX(StringID) FROM tblDestination
IF (@nextstringid IS NULL)
BEGIN
SET @nextstringid = 0
END
SET @nextstringid = @nextstringid + 1
RETURN @nextstringid
END
我的INSERT INTO .. SELECT语句,在这里调用它,如下所示:
INSERT INTO tblDestination(StringID, StringText)
SELECT dbo.GetNextStringID(), StringText FROM tblSource
问题是,这会导致主键冲突,因为该函数只运行一次,并且相同的PK值用于插入的所有行。
有更好的方法吗?我可以将 tblSource 中的PK添加到@nextstringid变量而不是1,但是这会产生PK一次跳过多个数字而不是递增1的可能性,这非常混乱。也许我可以使用 tblSource 的每一行的行号?有没有一种简单的方法可以做到这一点?
我还应该注意,我知道这会产生竞争条件,如果此查询一次从多个地方运行,则会出现关键冲突。它包含在一个事务中,以确保在出现问题时回滚。
SOLUTION:
我现在从我的功能中取出以下一行:
SET @nextstringid = @nextstringid + 1
这意味着它现在只返回 tblDestination
中的最大ID我现在正在INSERT INTO .. SELECT查询中添加当前行,如下所示:
INSERT INTO tblDestination(StringID, StringText)
SELECT dbo.GetNextStringID() + ROW_NUMBER() OVER (ORDER BY tblSource.ID), StringText
FROM tblSource
答案 0 :(得分:1)
要获取行号,您可以使用sql server的row_number函数
这是一个示例代码,用于演示您需要的内容...而不是3使用您已经拥有的@nextstringid变量,您应该很好。
create table tblSource(id integer identity, StringText varchar(200))
insert into tblSource values ('test1')
insert into tblSource values ('test2')
insert into tblSource values ('test3')
insert into tblSource values ('test4')
SELECT (row_number() over (order by id)) + 3 , id, StringText FROM tblSource t where t.id in (2,4)
注意我选择了#2和#4但行号仍然会给出两个连续的ID(在这种情况下为1 + 3和2 + 3(4和5)
希望它有所帮助。