web-dev-qa-db-ja.com

SQL ServerのINSERT INTO SELECTクエリで重複を避ける

次の2つのテーブルがあります。

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

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

Table1からTable2にデータを挿入する必要があります。次の構文を使用できます。

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

ただし、私の場合、Table2に重複するIDが存在する可能性があり(私の場合は、単に "1")、エラーをスローするため、再度コピーすることは望ましくありません。

私はこのようなものを書くことができます:

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

IF - ELSEを使用せずにこれを行うより良い方法はありますか?何らかの条件に基づいて、2つのINSERT INTO-SELECTステートメントを避けたい。

93
Ashish Gupta

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)

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)

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

3つのオプションのうち、LEFT JOIN/IS NULLはあまり効率的ではありません。 詳細についてはこのリンク を参照してください。

180
OMG Ponies

MySQLではこれを行うことができます。

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

SQL Serverには同様のものがありますか?

31
Duncan

同様の問題がありました。DISTINCTキーワードは魔法のように機能します。

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
7
Hunter Bingham

一意のインデックスでignore Duplicatesを使用する ここでIanCが提案したように は、オプションWITH IGNORE_DUP_KEYを使用してインデックスを作成する同様の問題の解決策でした

In backward compatible syntax
, WITH IGNORE_DUP_KEY is equivalent to WITH IGNORE_DUP_KEY = ON.

参照: index_option

3
Tazz602

SQL Serverから、一意キーのテーブルのインデックスを設定できます(一意である必要がある列)

From sql server right click on the table design select Indexes/Keys

Select column(s) that will be not duplicate , then type Unique Key

3
M. Salah

私は最近同じ問題に直面していました...
ここに、MS SQL Server 2017でうまくいったものがあります...
主キーは、表2のIDに設定する必要があります...
列と列のプロパティは、両方のテーブル間で同じでなければなりません。これは、以下のスクリプトを初めて実行するときに機能します。表1の重複IDは挿入されません...

2回目に実行すると、

PRIMARY KEY制約エラーの違反

これはコードです:

Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1
2
Vishane Naicker

DELETEの前の単純なINSERTで十分です。

DELETE FROM Table2 WHERE Id = (SELECT Id FROM Table1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1

保持するテーブルのIdnameのペアに応じて、Table1Table2に切り替えます。

0
Sacro

少し外れたトピックですが、データを新しいテーブルに移行したい場合、可能性のある重複が元のテーブルにあり、重複している可能性のある列がIDではない場合、GROUP BYでできます:

INSERT INTO TABLE_2
(name)
  SELECT t1.name
  FROM TABLE_1 t1
  GROUP BY t1.name
0
FullStackFool