Оператор SQL MERGE для обновления данных

У меня есть таблица с данными с именем energydata

он имеет всего три столбца

 (webmeterID, DateTime, kWh) 

У меня есть новый набор обновленных данных в таблице temp_energydata .

DateTime и webmeterID остаются неизменными. Но значения kWh нуждаются в обновлении из таблицы temp_energydata .

Как мне правильно написать T-SQL?

Предполагая, что вы хотите иметь фактическое заявление SQL Server MERGE :

 MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target USING dbo.temp_energydata AS source ON target.webmeterID = source.webmeterID AND target.DateTime = source.DateTime WHEN MATCHED THEN UPDATE SET target.kWh = source.kWh WHEN NOT MATCHED BY TARGET THEN INSERT (webmeterID, DateTime, kWh) VALUES (source.webmeterID, source.DateTime, source.kWh); 

Если вы также хотите удалить записи в целевом объекте, которых нет в исходном коде:

 MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target USING dbo.temp_energydata AS source ON target.webmeterID = source.webmeterID AND target.DateTime = source.DateTime WHEN MATCHED THEN UPDATE SET target.kWh = source.kWh WHEN NOT MATCHED BY TARGET THEN INSERT (webmeterID, DateTime, kWh) VALUES (source.webmeterID, source.DateTime, source.kWh) WHEN NOT MATCHED BY SOURCE THEN DELETE; 

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

Во-первых, есть несколько блогов, которые сообщают о проблемах параллелизма с оператором MERGE в более старых версиях SQL Server. Я не знаю, был ли этот вопрос когда-либо рассмотрен в последующих выпусках. В любом случае это можно в значительной степени решить, указав HOLDLOCK блокировки HOLDLOCK или SERIALIZABLE :

 MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target [...] 

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

Есть несколько других известных проблем с MERGE . (Обратите внимание, что поскольку Microsoft nuked Connect и не связала проблемы в старой системе с проблемами в новой системе, эти старые проблемы трудно отследить. Спасибо, Microsoft!) Из того, что я могу сказать, большинство из них не являются обычными проблемы или могут работать с такими же подсказками, как указано выше, но я их не тестировал.

Как бы то ни было, хотя у меня никогда не было никаких проблем с утверждением WITH (HOLDLOCK) , я всегда использую подсказку WITH (HOLDLOCK) , и я предпочитаю использовать это заявление только в самых простых случаях.

Я часто использовал Bacon Bits отличный ответ, поскольку я просто не могу запомнить синтаксис.

Но я обычно добавляю CTE в качестве дополнения, чтобы сделать часть DELETE более полезной, потому что очень часто вы захотите применить слияние только к части целевой таблицы.

 WITH target as ( SELECT * FROM dbo.energydate WHERE DateTime > GETDATE() ) MERGE INTO target WITH (HOLDLOCK) USING dbo.temp_energydata AS source ON target.webmeterID = source.webmeterID AND target.DateTime = source.DateTime WHEN MATCHED THEN UPDATE SET target.kWh = source.kWh WHEN NOT MATCHED BY TARGET THEN INSERT (webmeterID, DateTime, kWh) VALUES (source.webmeterID, source.DateTime, source.kWh) WHEN NOT MATCHED BY SOURCE THEN DELETE 

Если вам нужно просто обновить свои записи в energydata на основе данных в temp_energydata , считая, что temp_enerydata не содержит никаких новых записей, попробуйте это:

 UPDATE e SET e.kWh = t.kWh FROM energydata e INNER JOIN temp_energydata t ON e.webmeterID = t.webmeterID AND e.DateTime = t.DateTime 

Здесь работает sqlfiddle

Но если temp_energydata содержит новые записи, и вам нужно вставить его в energydata желательно с одним утверждением, тогда вам обязательно нужно ответить на этот вопрос, который дал Bacon Bits.

 UPDATE ed SET ed.kWh = ted.kWh FROM energydata ed INNER JOIN temp_energydata ted ON ted.webmeterID = ed.webmeterID 
 Update energydata set energydata.kWh = temp.kWh where energydata.webmeterID = (select webmeterID from temp_energydata as temp) 

ПРАВИЛЬНЫЙ ПУТЬ:

 UPDATE test1 INNER JOIN test2 ON (test1.id = test2.id) SET test1.data = test2.data 
  • Каковы варианты использования CHAR над VARCHAR в SQL?
  • t-sql получить все даты между двумя датами
  • Подстрока T-SQL - разделение имени и фамилии
  • Тестирование неравенства в T-SQL
  • Использование псевдонимов в разделе «Где» или «Альтернативный вариант»?
  • Объединение INSERT INTO и WITH / CTE
  • Создайте дату с дневного месяца и года с помощью T-SQL
  • Как конвертировать секунды в HH: MM: SS с использованием T-SQL
  • Найти все таблицы, содержащие столбец с указанным именем - MS SQL Server
  • Заменить новую строку в TSQL
  • Isoweek в SQL Server 2005
  • Interesting Posts

    Почему replaceAll терпит неудачу с «незаконной ссылкой на группу»?

    Где я могу разместить свои учетные данные при использовании Ivy и репозитория частной компании?

    Каков самый быстрый и безопасный способ протестировать новое программное обеспечение и при необходимости изменить все изменения?

    HttpClient.GetAsync (…) никогда не возвращается при использовании await / async

    Когда использовать val или def в чертах Scala?

    Внутренняя регистрация в cassandra CQL

    Как исправить ошибку «Обновление проекта Maven». Неподдерживаемый class IClasspathEntry = 4?

    Как изменить местоположение библиотеки в R?

    Windows 10 Start Menu останавливает работу

    Каков ваш любимый инструмент профилирования (для C ++)

    Есть ли способ отключить «максимизировать» привязку?

    Как сохранить выделенный текст при изменении фокуса в Microsoft Word / Excel

    Как разместить веб-шрифты google на моем собственном сервере?

    Справочные переменные и объекты в другом месте в форме

    Динамически создавать столбцы таблицы в JSF

    Давайте будем гением компьютера.