Stored Proc на SQL Server: Обновление или вставка
Быстрый ответ
В SQL Server для одновременного обновления существующих строк и вставки новых применяется оператор MERGE. За счёт выполнения действий upsert в рамках одного запроса, MERGE становится оптимальным решением для условного выполнения операций, в зависимости от наличия записи в базе данных:
MERGE TargetTable AS T
USING SourceTable AS S
ON T.Key = S.Key
WHEN MATCHED THEN
UPDATE SET T.Value = S.Value
WHEN NOT MATCHED THEN
INSERT (Key, Value) VALUES (S.Key, S.Value);

Изучение Upsert: основные принципы
Отдаем предпочтение обновлениям: повышаем производительность
Стратегия, основанная на приоритете обновления, помогает минимизировать количество обращений к таблице. Если запись предположительно имеется, то сначала выполняем обновление, а затем, с использованием @@rowcount, производим проверку на необходимость вставки:
UPDATE TargetTable
SET Value = S.Value
FROM SourceTable AS S
WHERE TargetTable.Key = S.Key;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO TargetTable (Key, Value)
SELECT Key, Value
FROM SourceTable
WHERE NOT EXISTS (
SELECT 1 FROM TargetTable WHERE Key = SourceTable.Key
);
END;
Работаем с параллельностью
При одновременном взаимодействии нескольких процессов с данными важно использовать транзакции с правильно установленными уровнями блокировок, чтобы поддержать целостность данных:
BEGIN TRANSACTION;
MERGE TargetTable WITH (HOLDLOCK) AS T
...
COMMIT TRANSACTION;
Рекомендуется также использовать уровень изоляции SERIALIZABLE для управления параллельными доступами.
Правильная обработка ошибок
Реализуйте стратегии обработки ошибок, чтобы при возникновении сбоя откатить транзакции и сохранить целостность данных:
BEGIN TRY
BEGIN TRANSACTION;
-- Логика upsert
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
-- Обработка ошибки
END CATCH;
Точный подход к проверкам существования
Перед реализацией проверки на существование с помощью SELECT оцените влияние на производительность и соответствие логики вашим требованиям.
Визуализация
Определите хранимую процедуру как набор инструментов для работы с базой данных, состоящий из двух основных элемнтов:
Набор инструментов (🧰): [Инструмент Вставки (🔨), Инструмент Обновления (🔧)]
Когда появляется новый объект для вставки (🔩):
Если объект соответствует существующей записи:
Используем Инструмент Обновления (🔧)
🔧 + 🔩 -> Запись обновлена! (🕳️)
Иначе:
Используем Инструмент Вставки (🔨)
🔨 + 🔩 -> Создана новая запись! (🕳️🆕)
Процедура выбирает инструмент на основе того, имеется ли для объекта соответствующая запись:
🧰🔍🔩 -> (🔧 или 🔨?) -> 🕳️ (🔄 или 🆕)
В результате выполнения процедуры:
Входные данные: [🔩, 🔩🆕, 🔩🆕]
С использованием 🧰:
Для существующего '🔩' применено: 🔧🔄🕳️
Для '🔩🆕' использовано: 🔨🆕🕳️
Для еще одного '🔩🆕' применено: 🔨🆕🕳️
Выбирая подходящий инструмент, вы можете максимально эффективно проводить операции вставки и обновления, обновляя базу данных без лишних действий.
Продвинутые подходы для мастеров Upsert
Улучшение производительности для Upsert
Любой подход upsert влияет на производительность. Мощный оператор MERGE, если его использовать неправильно, может оказаться ресурсоемким. Отслеживайте планы запросов и статистику, чтобы убедиться, что оператор действительно подходит для задачи.
Ожидайте новых функций SQL Server
Следите за обновлениями SQL Server, включающими улучшения выполнения операций upsert. Новые версии могут предлагать усовершенствования синтаксиса и производительности.
Преимущества знаний сообщества
Обращайтесь к блогам, форумам и другим источникам, чтобы узнать о реальной практике применения upsert в продвинутом производственном контексте.
Полезные материалы
- MERGE (Transact-SQL) – SQL Server | Microsoft Learn — официальная документация Microsoft по использованию оператора MERGE.
- Using hash values in SSIS to determine when to insert or update rows — руководство о применении хеш-значений в SSIS для определения момента вставки или обновления данных.
- Tutorial: Handle Concurrency with EF in an ASP.NET MVC 5 app | Microsoft Learn — учебное пособие по управлению параллельностью в .NET приложениях с использованием Entity Framework.