SQL Server违反PRIMARY KEY约束

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

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

  • test1 varchar(10)not null

  • test2 varchar(5)not null

  • test3 varchar(5)不为空

表B:

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

     PRIMARY KEY(test1)
);

我编写更新或插入合并行的查询:

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约束'PK__getSuppl__FCACF30EF3C2476C' . 无法在对象'表B'中插入重复键 . 重复键值为(test2 test3) .

为什么?

我的目标是比较表A中的每一行,如果行存在于B中,而其中一行没有test1,则更新else表中的插入到B.

谢谢

回答(2)

2 years ago

原因:表A中有一些数据表示test1 <> test2 test3 . 这样的数据会导致提到的错误;更重要的是,这种“错误的”数据也可能在表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:行('ABB','A','BC')将导致SQL错误;

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

解决方案:您可能希望从源(表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

希望能帮助到你 .

2 years ago

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

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

test1   test2    test3
  C       A        B

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

AB       A        B

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

您有数据问题 .