Игнорировать строку ошибки при обновлении или вставке SQL Server

Мой проект должен иметь дело с огромной базой данных. В худшем случае это может быть более 80 миллионов строк.

Теперь у меня есть 2 таблицы T1 и T2. Мне нужно скопировать данные из таблицы T1 в таблицу T2

  • если строка в таблице T1 уже существует в таблице T2 (тот же первичный ключ), то обновить данные других столбцов строки в T1 до T2
  • иначе вставить новую строку в T2

Сначала я использую цикл while, чтобы просмотреть 80-миллионную строку в T1, а затем обновить или вставить в T2. Это очень очень очень медленно, это занимает более 10 часов. Но если какая-либо строка вызывает ошибку, я могу ее проигнорировать и также перехватить ошибку.

После этого я использую запрос типа:

update Table2 
set T2.Column1 = T1.Column1,T2.Column2=T1.Column2 
from Table2 T2 JOIN Table1 T1 ON T1.ID=T2.ID

Это намного быстрее, всего 1-> 2 часа. Но если в какой-либо строке есть ошибка, запрос вообще не может быть выполнен.

Итак, мой вопрос:

  • Есть ли способ, которым приведенный выше запрос может игнорировать строку с ошибкой и продолжать выполнение с действительной строкой?

  • Если я не могу этого сделать, что я могу сделать, чтобы работать быстрее, чем первый метод, а также может поймать строку ошибки?

p/s: я попытался разбить таблицу на несколько небольших частей, а затем обновить или вставить всю небольшую часть одновременно, но это совсем не быстрее.

Я решил проблему с помощью моего второго метода. Я использую TRY_CAST, чтобы предотвратить исключение при вставке или обновлении строки. Любые недопустимые данные будут NULL. После окончания я сравниваю 2 таблицы и нахожу другую строку. Эта строка является строкой ошибки.


person user2500561    schedule 19.06.2013    source источник


Ответы (3)


Вы можете попробовать удалить существующие строки из T2, а затем выполнить массовую вставку всех строк из T1. Это зависит от количества существующих строк, если оно слишком велико, этот подход не сработает.

person Alexandr Mihalciuc    schedule 19.06.2013

Что касается функциональности, о которой вы просите, я бы предложил следующее:

MERGE INTO table2 target
USING
(
  SELECT id, column1, column2 FROM table1
) source ([id], [column1], [column2])
ON target.[Id] = source.[Id]
WHEN MATCHED THEN
    UPDATE SET 
        target.Colum1 = source.Column1,
                target.COlumn2 = source.Column2
WHEN NOT MATCHED BY SOURCE THEN
DELETE
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([Id], [Column1], [Column2])
    VALUES([Id], [Column1], [Column2])
;

Насчет игнорирования ошибок - я считаю этот путь неправильным. в этом отношении я бы приложил некоторые усилия для проверки данных

person Yaugen Vlasau    schedule 19.06.2013
comment
Спасибо. При выполнении получена ошибка: Msg 4104, уровень 16, состояние 1, строка 7 Не удалось связать составной идентификатор SOURCE.ID. - person user2500561; 19.06.2013
comment
Можете ли вы проверить, работает ли ваш оператор select в unsing. это может случиться, чем повторится та же ошибка. Если это так, то вы должны искать проблему в своем SELECT - person Yaugen Vlasau; 19.06.2013
comment
Спасибо. Я решил проблему с помощью моего второго метода. Я использую TRY_CAST, чтобы предотвратить исключение при вставке или обновлении строки. Любые недопустимые данные будут NULL. После окончания я сравниваю 2 таблицы и нахожу другую строку. Эта строка является строкой ошибки. - person user2500561; 20.06.2013

Я решил проблему с помощью моего второго метода. Я использую TRY_CAST, чтобы предотвратить исключение при вставке или обновлении строки. Любые недопустимые данные будут NULL. После окончания я сравниваю 2 таблицы и нахожу другую строку. Эта строка является строкой ошибки.

person user2500561    schedule 20.06.2013