简体   繁体   中英

SQL Server Violation of PRIMARY KEY constraint

I have 2 tables with same columns each one of the tables on different DB on the same server.

Table A it's exists but I don't created the table and the columns:

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

Table B:

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

     PRIMARY KEY(test1)
);

I write query that update or insert rows with 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

The first time that I run the query, it works perfectly, but the second time around, I get an error:

Violation of PRIMARY KEY constraint 'PK__getSuppl__FCACF30EF3C2476C'. Cannot insert duplicate key in object 'table B'. The duplicate key value is (test2+test3).

Why?

My goal is compare each row from table A and if the row exist in B and one of the columns without test1 is different then update else insert from table A to B.

Thanks

First, in SQL Server, you should never use varchar (and related types) without a length. Do you realize that varchar -- in this context -- only allows one character? If that is what you want, be explicit and use varchar(1) .

You would get the behavior if you have data in Table A that looks like:

test1   test2    test3
  C       A        B

The first time through the merge , the test1 will not match (assuming no C in the second table). The first time through, the code adds the row:

 AB       A        B

It still doesn't match C , so you will attempt to add it again. But, this will violate your primary key constraint. So, the insert fails.

You have a data problem.

Reason: There are some data in table A that test1 <> test2+test3. Such data will cause the error mentioned; And more than that, such "wrong" data may also generate "logically wrong" data in table B;

For example:

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');

Issue 1: row ('ABB', 'A', 'BC') will cause the SQL error;

Issue 2: row ('AB', 'A', 'C') in table A will override existing row ('A', 'B') in table B;

Solution: You might want to eliminate the "wrong" data from source (table A), for example:

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

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM