2012-12-12 78 views
4
INSERT INTO TABLE1 (COLUMN1, PRIMARY_KEY) 
    SELECT 
     COLUMN1, 
     (SELECT COALESCE(MAX(PRIMARY_KEY), 0) 
     FROM TABLE1) + 1 
    FROM 
     TABLE2 

错误:插入增量主键SQL多行

Violation of Primary Key constraint. Cannot insert duplicate key in object.

如何让我的第一行后,主键的增量?

我希望能够在同一时间添加项目列表,而不是插入它们的RBAR。

感谢您的帮助

回答

12
INSERT INTO TABLE1 (COLUMN1, PRIMARY_KEY) 
SELECT COLUMN1, 
     (SELECT COALESCE(MAX(PRIMARY_KEY),0) 
     FROM TABLE1) + row_number() over (order by 1/0) 
FROM TABLE 2 

仅凭这份声明中,ID将是连续的,例如如果Max(Primary Key)为99并且它插入4条记录,则它们将是100,101,102,103。如果多个进程同时插入,那么它很容易违反约束条件,但这并不是说它比你更糟糕无论如何都使用MAX(),这本来就是不安全的。

+0

这工作,感谢您的帮助。 – weewa

+0

@richardthekiwi我得到MAX(Primary_key)找到现有的最大值,然后你为每个相应的例子添加1,2,3,4。你能否向我解释一下(按1/0顺序排列)正在做什么? – JsonStatham

+1

@SelectDistinct row_number()必须与按顺序配对。由于缺乏一些好的命令,表达式“1/0”解析为no-op(未定义),所以row_number()可以自由地将数字以任意顺序分配给SELECT输出。 – RichardTheKiwi

-1

您不必检查MAX键,并增加1 1。使之成为IDENTITY(1,1) NOT NULL列,服务器会照顾它。然后使用;

INSERT INTO TABLE1 (COLUMN1) 
SELECT COLUMN1 
FROM TABLE 2 
+0

这是否意味着改变列设计?我无法做到这一点。 Primary_Key必须是INT – weewa

+1

* Primary_Key完全可以是INT *。使它成为'IDENTITY(1,1)'。是的,您必须更改色谱柱设计。 '不建议你的方法。' – Kaf

+0

我写的表是用于我们使用的程序,我没有选择更改设计。不幸的是,它应该如何设置它的设置。 – weewa

2

你可以试试这个:

DECLARE @CurrentPK INT 
SELECT @CurrentPK(MAX(PRIMARY_KEY) 

SELECT column1, ROW_NUMBER() OVER (ORDER BY column1) AS 'RowNumber' 
INTO #temp 
FROM Table2 

INSERT INTO TABLE1 
(COLUMN1, PRIMARY_KEY) 
SELECT COLUMN1,@CurrentPK+RowNumber 
FROM #temp 

当然,以防止竞争条件,你应该把这个在一个事务中,明确禁止其他刀片在同一时间发生。你最好的选择是使用try6 catch块的存储过程以及事务处理。

我希望您明白,在这种情况下避免交易不是一种选择。如果你没有专门使用交易,你会有两次tprocessses尝试使用相同的id号。事实上,这就是为什么获取最后一个id号的方法不推荐,因为使用它的数据库问题很容易。我知道你一直坚持这样做,但至少在将来学会不使用这种短视的反模式。

+0

你有一篇文章,我可以阅读这个了解更多?我将这些数据写入我们使用/购买的程序,并且他们的支持表示使用max()。所以我在这方面很愚蠢,但想要以正确的方式教育我自己。 – weewa

+1

不需要临时表,您可以将它作为SELECT FROM TABLE2上的派生表加入。但是,这种方式更清晰 –