插入中的SQL下一个可用PK

时间:2013-06-11 18:13:07

标签: sql sql-server-2008 tsql

我正在尝试使用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

1 个答案:

答案 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)

希望它有所帮助。