Обновить таблицу из временной таблицы

У меня есть таблица, в которой хранится информация о лекарствах из формуляра, которую необходимо ежедневно обновлять из центрального справочника. Временная таблица идентична таблице лекарств. Данные временной таблицы могут быть идентичны (и в большинстве случаев будут) основной таблице, либо в ней могут быть обновленные строки или новые строки.

У меня есть хранимая процедура для обновления основной таблицы, но она не работает, потому что не обновляет строки NULL (если во временной таблице есть новая строка).

Это MSSQL Server 2005.

Где я здесь ошибаюсь:

    -- Insert statements for procedure here
UPDATE [RX_Billing].[dbo].[FS_Drug]
SET [TRADENAME] = [RX_Billing].[dbo].[FS_Drug_TEMP].[TRADENAME]
  ,[CDM] = [RX_Billing].[dbo].[FS_Drug_TEMP].[CDM]
  ,[NDC] = [RX_Billing].[dbo].[FS_Drug_TEMP].[NDC]
  ,[IP_COST] = [RX_Billing].[dbo].[FS_Drug_TEMP].[IP_COST]
  ,[OP_COST] = [RX_Billing].[dbo].[FS_Drug_TEMP].[OP_COST]
  ,[HH_COST] = [RX_Billing].[dbo].[FS_Drug_TEMP].[HH_COST]
  ,[VAR_COST] = [RX_Billing].[dbo].[FS_Drug_TEMP].[VAR_COST]
  ,[LSTUPDATE] = [RX_Billing].[dbo].[FS_Drug_TEMP].[LSTUPDATE]
FROM [RX_Billing].[dbo].[FS_Drug]
RIGHT OUTER JOIN [RX_Billing].[dbo].[FS_Drug_TEMP] ON 
          [RX_Billing].[dbo].[FS_Drug].[TRADENAME] = 
                   [RX_Billing].[dbo].[FS_Drug_TEMP].[TRADENAME]

РЕДАКТИРОВАТЬ:

Я пошел с кодом Рори. Спасибо, это прекрасно работает.

Примечание для Ориона Эдвардса: UPSERT / MERGE - это именно то, что я хотел, но он не поддерживается в SQL Server 2005. Очевидно, это было запланировано, но не было выпущено в этом выпуске. Он доступен в Server 2008. (Из того, что мне сообщили в Interwebs.)

Ответов (3)

Решение

Стандартный способ - выполнить ОБНОВЛЕНИЕ, а затем ВСТАВИТЬ:

-- UPDATE rows using an INNER JOIN with matching TRADENAME. No need to update TRADENAME column.
UPDATE drug
SET [CDM] = tmp.[CDM]
  , [NDC] = tmp.[NDC]
  , [IP_COST] = tmp.[IP_COST]
  , [OP_COST] = tmp.[OP_COST]
  , [HH_COST] = tmp.[HH_COST]
  , [VAR_COST] = tmp.[VAR_COST]
  , [LSTUPDATE] = tmp.[LSTUPDATE]
FROM [RX_Billing].[dbo].[FS_Drug] drug
INNER JOIN [RX_Billing].[dbo].[FS_Drug_TEMP] tmp  
    ON drug.[TRADENAME] = tmp.[TRADENAME]

-- Insert rows that don't have matching TRADENAME
INSERT INTO drug
SELECT 
    tmp.[TRADENAME]
  , tmp.[CDM]
  , tmp.[NDC]
  , tmp.[IP_COST]
  , tmp.[OP_COST]
  , tmp.[HH_COST]
  , tmp.[VAR_COST]
  , tmp.[LSTUPDATE]
FROM [RX_Billing].[dbo].[FS_Drug] drug
RIGHT OUTER JOIN [RX_Billing].[dbo].[FS_Drug_TEMP] tmp 
    ON  drug.[TRADENAME] = tmp.[TRADENAME]
WHERE drug.[TRADENAME] IS NULL 

Вы также можете удалить или пометить как удаленные любые записи в препарате, которых больше нет в tmp. Сделайте это как отдельный оператор, такой же, как UPDATE, но с LEFT OUTER JOIN, где tmp.TRADENAME IS NULL.

Разве вы не хотите выполнить INSERT для новых строк и UPDATE для существующих строк? Обновление до INNER JOIN и добавление отдельного INSERT должно решить вашу проблему, если я правильно ее понимаю.

Вы можете попробовать сделать UPSERT (что в основном означает «если существует, обновить, иначе вставить»).

Я считаю, что SQL-сервер вызывает это MERGE