如何处理违反PRIMARY KEY约束错误

时间:2012-12-09 20:11:17

标签: sql sql-server database sql-server-2008

我的存储过程遇到了这个脚本的真正问题:

    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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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]
);

答案 2 :(得分: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))