Как избежать вставки повторяющихся записей при использовании слияния T-SQL оператор

Я пытаюсь вставить много записей с помощью оператора MERGE T-SQL, но мой запрос не выполняет INSERT, когда в исходной таблице есть повторяющиеся записи. Ошибка вызвана:

  1. Целевая таблица имеет первичный ключ, основанный на двух столбцах
  2. Исходная таблица может содержать повторяющиеся записи, которые нарушают ограничение первичного ключа целевой таблицы (выдается сообщение «Нарушение ограничения ПЕРВИЧНОГО КЛЮЧА»)

Я ищу способ изменить мой оператор MERGE так, чтобы он либо игнорировал повторяющиеся записи в исходной таблице, либо пытался / перехватить оператор INSERT, чтобы уловить возможные исключения (т.е. все другие операторы INSERT будут выполняться независимо от из нескольких плохих яиц, которые могут возникнуть) - или, может быть, есть лучший способ решить эту проблему?

Вот пример запроса того, что я пытаюсь объяснить. В приведенном ниже примере будет добавлено 100 тыс. Записей во временную таблицу, а затем будет предпринята попытка вставить эти записи в целевую таблицу -

ИЗМЕНИТЬ В моем исходном сообщении я включил только два поля в примеры таблиц, которые уступили место друзьям SO, чтобы дать DISTINCT решение, чтобы избежать дублирования в операторе MERGE. Я должен был упомянуть, что в моей реальной проблеме таблицы имеют 15 полей, и из этих 15 два поля являются КЛАСТЕРИРОВАННЫМ ПЕРВИЧНЫМ КЛЮЧОМ. Таким образом, ключевое слово DISTINCT не работает, потому что мне нужно ВЫБРАТЬ все 15 полей и игнорировать дубликаты на основе двух полей.

Я обновил приведенный ниже запрос, включив в него еще одно поле, col4. Мне нужно включить col4 в MERGE, но мне нужно только убедиться, что ТОЛЬКО col2 и col3 уникальны.

-- Create the source table
CREATE TABLE #tmp (
col2 datetime NOT NULL,
col3 int NOT NULL,
col4 int
)
GO

-- Add a bunch of test data to the source table
-- For testing purposes, allow duplicate records to be added to this table
DECLARE @loopCount int = 100000
DECLARE @loopCounter int = 0
DECLARE @randDateOffset int
DECLARE @col2 datetime
DECLARE @col3 int
DECLARE @col4 int

WHILE (@loopCounter) < @loopCount
BEGIN
    SET @randDateOffset = RAND() * 100000
    SET @col2 = DATEADD(MI,@randDateOffset,GETDATE())
    SET @col3 = RAND() * 1000
    SET @col4 = RAND() * 10
    INSERT INTO #tmp
    (col2,col3,col4)
    VALUES
    (@col2,@col3,@col4);

    SET @loopCounter = @loopCounter + 1
END

-- Insert the source data into the target table
-- How do we make sure we don't attempt to INSERT a duplicate record? Or how can we 
-- catch exceptions? Or?
MERGE INTO dbo.tbl1 AS tbl
    USING (SELECT * FROM #tmp) AS src
    ON (tbl.col2 = src.col2 AND tbl.col3 = src.col3)
    WHEN NOT MATCHED THEN 
        INSERT (col2,col3,col4)
        VALUES (src.col2,src.col3,src.col4);
GO
15
задан Jed 27 February 2018 в 12:23
поделиться