2012-12-12 114 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上的派生表加入。但是,這種方式更清晰 –