ЕСЛИ СУЩЕСТВУЕТ и оператор СЛИЯНИЯ

0

Вопрос

У меня есть данные, поступающие в одну таблицу из нескольких других таблиц, скажем: Table_A Затем у меня есть сохраненный процесс слияния, который берет данные из таблицы A, объединяет их с таблицей B.

Однако что-то, похоже, не так. Если я усекаю и загружаю данные, это работает нормально, но если я не усекаю и не загружаю, а просто получаю запрос каждый час, я получаю сообщение об ошибке, в котором говорится:

Msg 8672, Уровень 16, Состояние 1, Процедура Merge_Table_A, Строка 4 [Начальная Строка Пакета 0] Инструкция MERGE несколько раз пыталась ОБНОВИТЬ или УДАЛИТЬ одну и ту же строку. Это происходит, когда целевая строка совпадает более чем с одной исходной строкой. Инструкция MERGE не может ОБНОВЛЯТЬ или УДАЛЯТЬ одну и ту же строку целевой таблицы несколько раз. Уточните предложение ON, чтобы убедиться, что целевая строка соответствует не более чем одной исходной строке, или используйте предложение GROUP BY для группировки исходных строк.

Как я могу преодолеть это?

Я хочу, чтобы у меня была возможность постепенно загружать данные и не усекать нагрузки, но в то же время иметь сохраненный процесс, который обновляет, вставляет или не заботится о том, существует ли уже строка.

azure sql-merge sql-server
2021-11-24 01:52:34
1

Лучший ответ

1

Похоже, у вас есть повторяющиеся строки в целевой таблице, которые загружены из ваших предыдущих запусков.

Примечание.Сопоставление в слиянии не учитывает вставленные строки (даже дубликаты) при выполнении самого слияния.

Ниже приведен мой пример повторения с образцом данных:

Таблица 1: Исходные данные

enter image description here

Таблица 2: Таблица Taget

enter image description here

Оператор слияния:

MERGE tb2 AS Target
USING tb1   AS Source
 ON Source.firstname = Target.firstname and 
    Source.lastname = Target.lastname 

-- For Inserts
WHEN NOT MATCHED BY Target THEN
INSERT (firstname, lastname, updated_date) 
VALUES (Source.firstname, Source.lastname, source.updated_date)

-- For Updates
WHEN MATCHED THEN UPDATE SET
   Target.updated_date      = Source.updated_date

-- For Deletes
WHEN NOT MATCHED BY Source THEN
DELETE;

Когда выполняется слияние, оно вставляет все данные без каких-либо ошибок.

enter image description here

Новые данные в tb1:

enter image description here

Когда я запускаю инструкцию Merge, она выдает мне ту же ошибку, что и ваша.

enter image description here

В качестве обходного пути используйте один из следующих вариантов,

  1. Добавьте дополнительные условия, если это возможно, в предложение ON, чтобы однозначно идентифицировать данные.

  2. Удалите дубликаты из источника и объедините данные в tb2, как показано ниже.

     --temp table
     drop table if exists #tb1;
    
     select *  into #tb1 from (
         select *, row_number() over(partition by firstname, lastname order by firstname, lastname, updated_date desc) as rn from tb1) a
     where rn = 1 
    
     MERGE tb2 AS Target
     USING #tb1 AS Source
      ON Source.firstname = Target.firstname and 
         Source.lastname = Target.lastname 
    
     -- For Inserts
     WHEN NOT MATCHED BY Target THEN
     INSERT (firstname, lastname, updated_date) 
       VALUES (Source.firstname, Source.lastname, source.updated_date)
    
     -- For Updates
     WHEN MATCHED THEN UPDATE SET
        Target.updated_date     = Source.updated_date
    
     -- For Deletes
     WHEN NOT MATCHED BY Source THEN
       DELETE;
    

Данные успешно объединены в tb2.

enter image description here

2021-12-02 12:52:40

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................