2012-12-09 28 views
-1

我有我的這個腳本的存儲過程的一個現實問題PRIMARY KEY約束錯誤的衝突:如何應對

INSERT INTO #tr_TxnDetails  
    SELECT 
     b.pid, 
     b.etc 
    FROM tbl_SomeTableA as a 
    JOIN tbl_SomeTableB as b ON a.etc = b.etc 
     AND a.SomeColumn = b.SomeColumn 

    -- This is throwing error: Violation of PRIMARY KEY constraint. Cannot insert duplicate key in object 'dbo.tr_TxnDetails'. 
    INSERT INTO tr_TxnDetails 
    ([id], [etc]) 
    SELECT a.[id], 
      a.[etc] 
    FROM #tr_TxnDetails as a 
    WHERE not exists (select 1 from tr_TxnDetails as b where a.[id] = b.[id]); 

如何確保在INSERT INTO聲明時tr_TxnDetails它不插入一行具有相同的主鍵:pid

+0

這是可能的重複http://stackoverflow.com/questions/2136273/primary-key-duplicate-record-bypass-to-next-insert – Anri

+0

你爲什麼試圖插入一個重複鍵的行?這在邏輯上是否有意義?不要只是沉默錯誤 - 消除潛在的問題。 – usr

+0

@usr - xybrek沒有試圖插入一個重複鍵的行,他試圖避免這樣做 –

回答

0
INSERT INTO #tr_TxnDetails  
SELECT 
    b.pid, 
    b.etc 
FROM tbl_SomeTableA as a 
JOIN tbl_SomeTableB as b ON a.etc = b.etc 
    AND a.SomeColumn = b.SomeColumn 
    WHERE b.pid NOT IN (select distinct id from tr_TxnDetails) --<<-- 

INSERT INTO tr_TxnDetails 
([id], [etc]) 
SELECT a.[id], 
     a.[etc] 
FROM #tr_TxnDetails as a 
0

我認爲,你的第一個INSERT ... SELECT語句重複生產,然後將這些副本都導致你的第二個選擇主鍵錯誤。您的WHERE EXISTS子句僅防止插入與現有行重複的副本。

我會來找你的查詢後,卻只是爲了顯示你可以很簡單地導致此錯誤與下面一組語句:

create table TableA 
(
    Pid INT PRIMARY KEY, 
    etc INT 
); 


INSERT INTO TableA 
SELECT 1, 0 
UNION 
SELECT 1, 2 

,這裏是錯誤:

Violation of PRIMARY KEY constraint 'PK__TableA__C57059387F60ED59'. Cannot insert duplicate key in object 'dbo.TableA'.: INSERT INTO TableA SELECT 1, 0 UNION SELECT 1, 2 

現在回到您的查詢,簡單的重寫是確保查詢只返回DISTINCT行:

INSERT INTO #tr_TxnDetails  
SELECT DISTINCT 
    b.pid, 
    b.etc 
FROM tbl_SomeTableA as a 
JOIN tbl_SomeTableB as b ON a.etc = b.etc 
    AND a.SomeColumn = b.SomeColumn 

INSERT INTO tr_TxnDetails 
([id], [etc]) 
SELECT a.[id], 
     a.[etc] 
FROM #tr_TxnDetails as a 
WHERE not exists (select 1 from tr_TxnDetails as b where a.[id] = b.[id]); 

這應該對你有用。

還有一點就是,在你的例子中,除非有充分的理由,例如這兩個語句之間的某些其他處理,否則應該取消臨時表步驟。下面是改寫查詢:

INSERT INTO tr_TxnDetails  
SELECT DISTINCT 
     b.pid, 
     b.etc 
FROM tbl_SomeTableA as a 
JOIN tbl_SomeTableB as b ON a.etc = b.etc 
    AND a.SomeColumn = b.SomeColumn 
WHERE not exists (
    select 1 
    from tr_TxnDetails as c 
    where a.[id] = C.[id] 
); 
0
DECLARE @ChoiceID INT 

SET @ChoiceID = (SELECT MAX([CHOICE_ID]) FROM BI_QUESTION_CHOICE) -- FOR SOMETABLE.ID 

INSERT BI_QUESTION_CHOICE 
       (
        [choice_id], 
        [choice_descr], 
        [sequence], 
        [question_id], 
        [is_correct], 
        [created_by], 
        [created_dt], 
        [modified_by], 
        [modified_dt] 
       ) 
       (SELECT @ChoiceID+ROW_NUMBER() OVER (ORDER BY @ChoiceID), 
        pref.value('(ChoiceText/text())[1]', 'varchar(50)'), 
        pref.value('(Sequence/text())[1]', 'varchar(50)') , 
        @QuestionID, 
        pref.value('(IsCorrect/text())[1]', 'bit'), 
        'mbathini', 
        GETDATE(), 
        'mbathini', 
        GETDATE() 
       FROM @xmlstring.nodes('/ArrayOfBI_QA_ChoiceEntity/BI_QA_ChoiceEntity') AS Responses(pref))