Подтвердить что ты не робот

Любой способ SQLBulkCopy "вставить или обновить, если существует"?

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

Если нет, то какой самый эффективный способ сделать это? Опять же, я говорю о таблице с миллионами записей.

Спасибо

4b9b3361

Ответ 2

Не в один шаг, но в SQL Server 2008 вы можете:

  • объемная загрузка в промежуточную таблицу
  • применить инструкцию MERGE для обновления/вставки в вашу реальную таблицу

Подробнее о инструкции MERGE

Ответ 3

Вместо создания новой временной таблицы, которая BTW потребляет больше места и памяти.

Я создал триггер с INSTEAD OF INSERT и использовал внутри оператора MERGE.

Но не забудьте добавить параметр SqlBulkCopyOptions.FireTriggers в SqlBulkCopy.

Это мои два цента.

Ответ 4

Я опубликовал пакет nuget (SqlBulkTools) для решения этой проблемы.

Вот пример кода, который обеспечит массовую поддержку.

var bulk = new BulkOperations();
var books = GetBooks();

using (TransactionScope trans = new TransactionScope())
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager
    .ConnectionStrings["SqlBulkToolsTest"].ConnectionString))
    {
        bulk.Setup<Book>()
            .ForCollection(books)
            .WithTable("Books")
            .AddAllColumns()
            .BulkInsertOrUpdate()
            .MatchTargetOn(x => x.ISBN)
            .Commit(conn);
    }

    trans.Complete();
}

Для очень больших таблиц есть варианты добавить блокировки таблиц и временно отключить некластеризованные индексы. Посмотрите SqlBulkTools Documentation для большего количества примеров.

Ответ 5

Другой альтернативой может быть не использование временной таблицы, а использование хранимой процедуры с параметром таблицы. Передайте datatable в sp и выполните слияние там.