SQL Server违反PRIMARY KEY约束

时间:2017-11-05 15:29:02

标签: sql sql-server-2012

我在同一台服务器上的不同数据库中有两个表,每个表都有相同的列。

表A它存在,但我没有创建表格和列:

  • test1 varchar(10)not null
  • test2 varchar(5)not null
  • test3 varchar(5)not null

表B:

CREATE TABLE B
(
     test1 as test2 + test3 PERSISTED NOT NULL,
     test2 varchar NOT NULL,
     test3 varchar NOT NULL

     PRIMARY KEY(test1)
);

我编写了更新或插入带有merge的行的查询:

MERGE B AS TARGET
USING A AS SOURCE 
ON (TARGET.test1 = SOURCE.test1) 

WHEN MATCHED AND (TARGET.test2 <> SOURCE.test2 OR TARGET.test3 <> SOURCE.test3 
   THEN
      UPDATE SET TARGET.test2 = SOURCE.test2,
                 TARGET.test3 = SOURCE.test3 

WHEN NOT MATCHED BY TARGET THEN 
    INSERT (test2, test3) 
    VALUES (SOURCE.test2, SOURCE.test3);
GO

我第一次运行查询时,它运行正常,但第二次,我收到错误:

  

违反PRIMARY KEY约束&#39; PK__getSuppl__FCACF30EF3C2476C&#39;。无法在对象&#39;表B&#39;中插入重复键。重复键值为(test2 + test3)。

为什么?

我的目标是比较表A中的每一行,如果该行存在于B中,而其中一列没有test1则不同,则更新从表A到B的其他插入。

由于

2 个答案:

答案 0 :(得分:2)

首先,在SQL Server中,不应使用varchar(和相关类型)而不使用长度。你是否意识到varchar - 在这种情况下 - 只允许一个角色?如果这是您想要的,请明确并使用varchar(1)

如果表A中的数据如下所示,您将获得该行为:

test1   test2    test3
  C       A        B

第一次通过merge时,test1将不匹配(假设第二个表中没有C)。第一次,代码添加了行:

 AB       A        B

它仍然与C不匹配,因此您将尝试再次添加它。但是,这将违反您的主键约束。因此,插入失败。

您遇到了数据问题。

答案 1 :(得分:0)

原因: 表A中有一些数据表示test1&lt;&gt;测试2 + TEST3。这样的数据会导致提到的错误; 更重要的是,这样的&#34;错误&#34;数据也可能产生逻辑错误&#34;表B中的数据;

例如:

CREATE TABLE A
(
     test1 varchar(10) NOT NULL,
     test2 varchar(10) NOT NULL,
     test3 varchar(10) NOT NULL
     PRIMARY KEY(test1)
);
CREATE TABLE B
(
     test1 as test2 + test3 PERSISTED NOT NULL,
     test2 varchar(10) NOT NULL,
     test3 varchar(10) NOT NULL
     PRIMARY KEY(test1)
);
insert into A values ('AB', 'A', 'C');
insert into B values ('A', 'B');
insert into A values ('ABB', 'A', 'BC');

问题1:行(&#39; ABB&#39;,&#39; A&#39;,&#39; BC&#39;)将导致SQL错误;

问题2:表A中的行(&#39; AB&#39;,&#39; A&#39;,&#39; C&#39;)将覆盖现有行(&#39; A&#39;表B中的,&#39; B&#39;;

解决方案: 你可能想要消除错误的&#34;来自源(表A)的数据,例如:

MERGE B AS TARGET
USING A AS SOURCE 
ON (TARGET.test1 = SOURCE.test1 AND SOURCE.test1 = SOURCE.test2 + SOURCE.test3 ) 

WHEN MATCHED AND (TARGET.test2 <> SOURCE.test2 OR TARGET.test3 <> SOURCE.test3) 
   THEN
      UPDATE SET TARGET.test2 = SOURCE.test2,
                 TARGET.test3 = SOURCE.test3 

WHEN NOT MATCHED BY TARGET AND (SOURCE.test1 = SOURCE.test2 + SOURCE.test3) THEN 
    INSERT (test2, test3) 
    VALUES (SOURCE.test2, SOURCE.test3);
GO

希望它有所帮助。