MERGE для обновления

Fire83
Дата: 21.06.2011 13:26:11
Добрый день, коллеги!

Вопрос такой - для синхронизации таблиц в дата варехаузе (MS SQL 2008 R2 ) используем MERGE оператор, вида:

MERGE table1 as T
USING ( SELECT .. FROM S ) ON ( T.Key = S.Key)
      
WHEN MATCHED AND ( T.Field1 <> S.Field1 OR T.Field2 <> S.Field2 OR T.Field3 <> S.Field3...25 полей ) THEN 
  UPDATE 
   SET
       T.Field1 = S.Field1
      ,T.Field2 = S.Field2 
      ,T.Field3 = S.Field3
.. 
 25 полей
    
WHEN NOT MATCHED THEN 
  INSERT ...

Все работает, но если поля нуловые (суммы) то код получается следующий:

MERGE table1 as T
USING ( SELECT .. FROM S ) ON ( T.Key = S.Key)
      
WHEN MATCHED AND ( ( T.Field1 <> S.Field1 OR ( T.Field1 IS NOT NULL AND S.Field1 IS NULL) OR ( T.Field1 IS NULL AND S.Field1 IS NOT NULL)
                              OR  и т.д. 25 полей ) THEN 
  UPDATE 
   SET
       T.Field1 = S.Field1
      ,T.Field2 = S.Field2 
      ,T.Field3 = S.Field3
.. 
 25 полей
    
WHEN NOT MATCHED THEN 
  INSERT ...

Иными словами код приобретает ужасный вид.
Сначала думал для упрощения использовать SET ANSI_NULLS, но стремно т.к.
BOL
In a future version of SQL Server, ANSI_NULLS will always be ON and any applications that explicitly set the option to OFF will generate an error. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.

Если ли красивое решение проблемы в текущей версии или только остается мирится таким кодом и ждать добавления
оператора IS NOT DISTINCT FROM ?
iap
Дата: 21.06.2011 13:29:29
AND NOT EXISTS(SELECT T.Field1,T.Field2,...,T.Field25 INTERSECT SELECT S.Field1,S.Field2,...,S.Field25)
iap
Дата: 21.06.2011 13:32:05
Fire83,
SET ANSI_NULLS
влияет только на сравнение с литералом NULL и с переменной, равной NULL.
На сравнение полей между собой не влияет.
Да и в следующих версиях всегда будет иметь стандартное (по ANSI стандарту) неизменяемое значение.
iap
Дата: 21.06.2011 13:34:50
iap
AND NOT EXISTS(SELECT T.Field1,T.Field2,...,T.Field25 INTERSECT SELECT S.Field1,S.Field2,...,S.Field25)
Для интереса можно попробовать и
AND EXISTS(SELECT T.Field1,T.Field2,...,T.Field25 EXCEPT SELECT S.Field1,S.Field2,...,S.Field25)
но здесь неоднократно отмечалось, что при INTERSECTе бывает, что сервер и индексы умеет использовать, если они есть.
Смотреть в плане надо.
Fire83
Дата: 21.06.2011 13:48:43
iap,

Спасибо, похоже что что нужно!