'Update only when not exists

I am trying to update table tbl1 using table tbl2 but only if combination tbl2 (tbl2_col1,tbl2_col2) rows don't exist in tbl1. In this case I want to update 000006 both row to match those in tbl2. I am getting an error on the query:

Violation of PRIMARY KEY constraint 'PK__tbl1__A1B90E2508A9C3D2'. Cannot insert duplicate key in object 'dbo.tbl1'. The duplicate key value is (000006, GG1).

What am I missing?

tbl2 :

tbl2_col1  tbl2_col2
000002     B
000003     C
000004     D
000005     Z
000006     GG1
000006     YY

tbl1:

tbl1_col1  tbl1_col2
000002     B
000003     C
000004     D
000005     Z
000006     GG
000006     YY

Query 1:

UPDATE tbl1 SET
    tbl1_col2 = s.tbl2_col2
FROM tbl2 s
WHERE tbl1.tbl1_col1 = s.tbl2_col1
AND NOT EXISTS (
    SELECT 1
    FROM tbl1
    WHERE tbl1_col2 = s.tbl2_col2 AND tbl1_col1 = s.tbl2_col1
)


Solution 1:[1]

As already mentioned, it is best to try it with a select first, to see what will be the outcome.
You can use a right join for this

select t1.tbl1_col1,
       t1.tbl1_col2,
       tbl2.tbl2_col1,
       tbl2.tbl2_col2
from   tbl1 t1
  right join tbl2 on t1.tbl1_col1 = tbl2.tbl2_col1
                 and t1.tbl1_col2 = tbl2.tbl2_col2 
where  t1.tbl1_col1 is null

this will get you this result, which actually are all rows in tbl2 that you don't have in tbl1

tbl1_col1 tbl1_col2 tbl2_col1 tbl2_col2
null null 000006 GG1

So from here we can easily create our update statement, because we can simply use the query above in our update statement.

update t1
set    t1.tbl1_col2 = t.tbl2_col2
from   tbl1 t1
  join ( select --t1.tbl1_col1, 
                --t1.tbl1_col2,
                tbl2.tbl2_col1,
                tbl2.tbl2_col2
         from   tbl1 
           right join tbl2 on tbl1.tbl1_col1 = tbl2.tbl2_col1
                          and tbl1.tbl1_col2 = tbl2.tbl2_col2 
         where  tbl1.tbl1_col1 is null
       ) t on t1.tbl1_col1 = t.tbl2_col1

and after that tbl1 will look like this

tbl1_col1 tbl1_col2
000002 B
000003 C
000004 D
000005 Z
000006 GG1
000006 GG1

I also made a DBFiddle here

EDIT

However, if you need this result

tbl1_col1 tbl1_col2
000002 B
000003 C
000004 D
000005 Z
000006 GG1
000006 YY

then change the update query to this
(The only difference is the additional where clause at the end)

update t1
set    t1.tbl1_col2 = t.tbl2_col2
from   tbl1 t1
  join ( select tbl2.tbl2_col1,
                tbl2.tbl2_col2
         from   tbl1 
           right join tbl2 on tbl1.tbl1_col1 = tbl2.tbl2_col1
                          and tbl1.tbl1_col2 = tbl2.tbl2_col2 
         where  tbl1.tbl1_col1 is null
       ) t on t1.tbl1_col1 = t.tbl2_col1
where not exists ( select 1 
                   from   tbl2 
                   where  tbl2.tbl2_col1 = t1.tbl1_col1
                   and    tbl2.tbl2_col2 = t1.tbl1_col2
                 )

And again, here is a DBFiddle

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1