Любой способ SQLBulkCopy "вставить или обновить, если существует"?
Мне нужно периодически обновлять очень большую таблицу, и SQLBulkCopy отлично подходит для этого, только у меня есть индекс с двумя столбцами, который предотвращает дублирование. Есть ли способ использовать SQLBulkCopy как "вставить или обновить, если существует"?
Если нет, то какой самый эффективный способ сделать это? Опять же, я говорю о таблице с миллионами записей.
Спасибо
Ответы
Ответ 1
Я бы навалом загружал данные во временную промежуточную таблицу, а затем выполнил обновление в финальной таблице. См. http://www.databasejournal.com/features/mssql/article.php/3739131/UPSERT-Functionality-in-SQL-Server-2008.htm для примера выполнения upsert.
Ответ 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 и выполните слияние там.