Пропустить/игнорировать/не вставлять повторяющиеся строки

Вот что я хочу: Скопируйте строки из tableA в tableB, но не в любые строки, которые уже находятся в таблицеB. нет PK или identiy, я просто хочу проверить каждое поле и не вставлять, если есть соответствующая строка со всеми одинаковыми полями. Я пробовал как с INSERT, так и с MERGE:

--try with INSERT
 INSERT TableB(col1,col2,col3,col4,col5,col6, etc.)
 SELECT (col1,col2,col3,col4,col5,col6, etc.) 
 FROM tableA as src
 WHERE NOT EXISTS (SELECT 1 FROM TableB as T
 WHERE 
 T.col1 = src.col1 AND
 T.col2 = src.col2 AND
 T.col3 = src.col3 AND
 T.col4 = src.col4 AND
 T.col5 = src.col5 AND
 T.col6 = src.col6, etc.)

Я также пытался использовать MERGE:

MERGE INTO tableA src
 USING tableB T
 ON (
 T.col1 = src.col1 AND
 T.col2 = src.col2 AND
 T.col3 = src.col3 AND
 T.col4 = src.col4 AND
 T.col5 = src.col5 AND
 T.col6 = src.col6, etc.)
 WHEN NOT MATCHED THEN
 INSERT (col1,col2,col3,col4,col5,col6, etc.)
 VALUES (col1,col2,col3,col4,col5,col6, etc.);

Оба делают то же самое: я сделаю вставку (или слияние), и изначально все строки импортируются, что хорошо, но затем при второй попытке (которая должна вставлять/объединять 0 строк) она будет вставлять/слияние 60% строк.

Я считаю, что проблема в том, что у меня нет ПК, что я видел на других сообщениях здесь. Я просто хочу совместить все поля, возможно, так? Я что-то пропустил?

Спасибо за консультацию/руководство!

4 ответа

Вы можете использовать EXCEPT

INSERT INTO table1
SELECT * from table2
EXCEPT 
SELECT * from table1;

Посмотрите на скрипку здесь


Я предполагаю, что проблема в NULL. Попробуйте выполнить запрос как:

INSERT TableB(col1,col2,col3,col4,col5,col6, etc.)
SELECT (col1,col2,col3,col4,col5,col6, etc.) 
FROM tableA as src
WHERE NOT EXISTS (SELECT 1 FROM TableB as T
 WHERE (T.col1 = src.col1 or t.col1 is null and src.col1 is null) AND
 (T.col2 = src.col2 or t.col2 is null and src.col2 is null) AND
 . . .


Вы можете использовать LEFT OUTER JOIN в вашем заявлении select, чтобы найти записи, где все столбцы NULL, например:

INSERT INTO tableB (col1,col2,col3,col4,col5,col6, etc.)
 SELECT (A.col1, A.col2, A.col3, A.col4, A.col5, A.col6, etc.) 
 FROM tableA as A
 LEFT OUTER JOIN tableB AS B ON A.col1 = B.col1 AND A.col2 = B.col2 AND 
 A.col3 = B.col3 ... /* all the way to B.col99 or whatever */
 WHERE B.col1 IS NULL AND B.col2 IS NULL AND B.col3 IS NULL ... 
 /* all the way to B.col99 or whatever your last column is */


Ваша проблема может иметь отношение к значениям NULL. Следующий script гарантирует, что если существуют существующие строки с несколькими столбцами NULL, они совпадают.

--Create the sample source table.
--Notice that the columns allow NULL values...
CREATE TABLE #T1
(
 Col1 nvarchar(10) NULL,
 Col2 nvarchar(10) NULL,
 Col3 nvarchar(10) NULL
)
--Create the sample destination table.
CREATE TABLE #T2
(
 Col1 nvarchar(10) NULL,
 Col2 nvarchar(10) NULL,
 Col3 nvarchar(10) NULL
)
GO
--Populate the source table with some initial rows
--Notice that some column values are NULL
INSERT INTO #T1 (Col1,Col2,Col3) 
VALUES ('A','B',NULL),
 ('D','E','F'), 
 ('G',NULL,'I');
GO
--Verify the data in the tables 
--Table #T1 should have data in it
SELECT * FROM #T1;
--Table #T2 should be empty
SELECT * FROM #T2;
GO
--Copy the rows from #T1 to #T2
--where there are no matching rows.
INSERT INTO #T2(Col1,Col2,Col3)
SELECT 
 T1.Col1,T1.Col2,T1.Col3 
FROM #T1 AS T1
LEFT OUTER JOIN #T2 AS T2
ON IsNull(T1.Col1,'') = IsNull(T2.Col1,'')
AND IsNull(T1.Col2,'') = IsNull(T2.Col2,'')
AND IsNull(T1.Col3,'') = IsNull(T2.Col3,'')
WHERE T2.Col1 IS NULL AND T2.Col2 IS NULL AND T2.Col3 IS NULL
GO
--Verify the data in the tables. They should be the same now.
SELECT * FROM #T1;
SELECT * FROM #T2;
GO
--Add a some new rows to #T1
INSERT INTO #T1 (Col1,Col2,Col3) 
VALUES ('J','K','L'),
 ('M',NULL,'O'),
 ('P','Q','R'),
 ('A','B','C'); --THIS LAST ROW DOES NOT MATCH THE EXISTING A,B,NULL ROW AND WILL BE INSERTED ON MERGE
GO
--Merge the tables, and yes you could use MERGE where the ON clause handled NULLs
INSERT INTO #T2(Col1,Col2,Col3)
SELECT 
 T1.Col1,T1.Col2,T1.Col3 
FROM #T1 AS T1
LEFT OUTER JOIN #T2 AS T2
ON IsNull(T1.Col1,'') = IsNull(T2.Col1,'')
AND IsNull(T1.Col2,'') = IsNull(T2.Col2,'')
AND IsNull(T1.Col3,'') = IsNull(T2.Col3,'')
WHERE T2.Col1 IS NULL AND T2.Col2 IS NULL AND T2.Col3 IS NULL
GO
--Verify the new data is in both tables.
SELECT * FROM #T1;
SELECT * FROM #T2;
GO
--Cleanup
DROP TABLE #T1;
DROP TABLE #T2;

licensed under cc by-sa 3.0 with attribution.