views:

520

answers:

2

I have following two tables:-

Table1
-------------
ID Name
1  A
2  B
3  C


Table2
--------
ID Name
1  Z

I need to insert data from Table1 to Table2 and I can use following sytax for the same:-

INSERT INTO Table2(Id, Name) SELECT Id, Name FROM Table1

However, In my case duplicate Ids might exist in Table2 (In my case Its Just "1") and I dont want to copy that again as that would throw an error.

I can write something like this:-

IF NOT EXISTS(SELECT 1 FROM Table2 WHERE Id=1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 
ELSE
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 WHERE Table1.Id<>1

Is there a better way to do this without using IF - ELSE? I want to avoid two INSERT INTO-SELECT statements based on some condition.

Any help is appreciated.

+4  A: 

Using NOT EXISTS:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE NOT EXISTS(SELECT id
                    FROM TABLE_2 t2
                   WHERE t2.id = t1.id)

Using NOT IN:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE t1.id NOT IN (SELECT id
                       FROM TABLE_2)

Using LEFT JOIN/IS NULL:

INSERT INTO TABLE_2
  (id, name)
   SELECT t1.id,
          t1.name
     FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.id = t1.id
    WHERE t2.id IS NULL

Of the three options, the LEFT JOIN/IS NULL is less efficient. See this link for more details.

OMG Ponies
Thank you......
ydobonmai
Just a clarification on the NOT EXISTS version, you'll need a WITH(HOLDLOCK) hint or no locks will be taken (because there are no rows to lock!) so another thread could insert the row under you.
IDisposable
Interesting, because I have always believed joining to be faster than sub-selects. Perhaps that is for straight joins only, and not applicable to left joins.
Duncan
Duncan, joining is often faster that subselects when they are correlated subqueries. If you have the subquery up in the select list a join will often be faster.
HLGEM
+1  A: 

In MySQL you can do this:

INSERT IGNORE INTO Table2(Id, Name) SELECT Id, Name FROM Table1

Does SQL Server have anything similar?

Duncan
+1 for educating me on this . Very nice syntax. Definitely shorter and better than the one I used. Unfortunately Sql server does not have this.
ydobonmai