2014-09-29 6 views
1
MERGE DestinationTable AS D 
USING SourceTable AS S 
ON D.Alternate_ID = S.ID 
WHEN MATCHED AND 
(
     D.ID <> S.ID 
    OR D.col1 <> S.col1 
    OR D.col2 <> S.col2 
    OR D.col3 <> S.col3 
    OR D.col4 <> S.col4 
    OR D.col5 <> S.col5 
    OR D.col6 <> S.col6 
    OR D.col7 <> S.col7 
    OR D.col8 <> S.col8 
) 

Привет всем, я пытаюсь обновить DestinationTable, если какое-либо значение столбца в SourceTable было изменено с помощью вышеприведенного фрагмента инструкции Merge.Сравнение NULL со строками в SQL Server

Однако, если у меня есть значение NULL в столбце назначения и строка или значение бита в источнике, сравнение D.col8 <> S.col8 вернет false из-за того, как SQL обрабатывает сравнения со значениями NULL. В результате DestinationTable не обновляется новыми значениями из SourceTable.

Каков наилучший способ справиться с этой проблемой. Если D.Col8 является NULL, а S.Col8 имеет строку или значение бита, я все равно хочу вернуть значение true для выражения, например D.col8 <> S.col8

SO, если у меня есть значение «Test» в S.Col8 и NULL в D.Col8, я хочу, чтобы обновить столбец назначения от NULL в "Test"

+0

Выполняет обновление, если никакие столбцы не на самом деле * не изменили измеримую стоимость, которую вам нужно устранить? –

+0

d.col8 не является нулевым и d.col8 <> s.col8 – DwB

+0

@Damien_The_Unbeliever, Да, это желательно. – StackTrace

ответ

3
MERGE DestinationTable AS D 
USING SourceTable AS S 
ON D.Alternate_ID = S.ID 
WHEN MATCHED AND 
(
     D.ID <> S.ID 
    OR (D.col1 IS NULL AND S.col1 IS NOT NULL) 
     OR (D.col1 IS NOT NULL AND S.col1 IS NULL) 
     OR D.col1 <> S.col1 
    OR (D.col2 IS NULL AND S.col2 IS NOT NULL) 
     OR (D.col2 IS NOT NULL AND S.col2 IS NULL) 
     OR D.col2 <> S.col2 
    OR (D.col3 IS NULL AND S.col3 IS NOT NULL) 
     OR (D.col3 IS NOT NULL AND S.col3 IS NULL) 
     OR D.col3 <> S.col3 
    OR (D.col4 IS NULL AND S.col4 IS NOT NULL) 
     OR (D.col4 IS NOT NULL AND S.col4 IS NULL) 
     OR D.col4 <> S.col4 
    OR (D.col5 IS NULL AND S.col5 IS NOT NULL) 
     OR (D.col5 IS NOT NULL AND S.col5 IS NULL) 
     OR D.col5 <> S.col5 
    OR (D.col6 IS NULL AND S.col6 IS NOT NULL) 
     OR (D.col6 IS NOT NULL AND S.col6 IS NULL) 
     OR D.col6 <> S.col6 
    OR (D.col7 IS NULL AND S.col7 IS NOT NULL) 
     OR (D.col7 IS NOT NULL AND S.col7 IS NULL) 
     OR D.col7 <> S.col7 
    OR (D.col8 IS NULL AND S.col8 IS NOT NULL) 
     OR (D.col8 IS NOT NULL AND S.col8 IS NULL) 
     OR D.col8 <> S.col8 
) 
+0

это решение не будет обрабатывать случай null в исходной таблице – Paolo

+0

Отмечено это как ответ, потому что ISNULL (D.col1, '') <> S.col1 терпит неудачу, если тип данных столбца является уникальным идентификатором. – StackTrace

+0

@Paolo SO заявила, что таблица назначения может иметь NULL, а не источник. Зачем проверять что-то, что невозможно? –

0

Попробуйте это:

... 
WHEN MATCHED AND 
(
    ISNULL(D.ID, '') <> S.ID 
    OR ISNULL(D.col1, '') <> S.col1 
    OR ISNULL(D.col2, '') <> S.col2 
    OR ISNULL(D.col3, '') <> S.col3 
    OR ISNULL(D.col4, '') <> S.col4 
    OR ISNULL(D.col5, '') <> S.col5 
    OR ISNULL(D.col6, '') <> S.col6 
    OR ISNULL(D.col7, '') <> S.col7 
    OR ISNULL(D.col8, '') <> S.col8 
) 
0

попробовать что-то вроде

MERGE DestinationTable AS D 
USING SourceTable AS S ON D.Alternate_ID = S.ID 
WHEN MATCHED AND 
(
    ISNULL(D.ID, '') <> ISNULL(S.ID,'') 
    OR ISNULL(D.col1, '') <> ISNULL(S.col1,'') 
    OR ISNULL(D.col2, '') <> ISNULL(S.col2,'') 
    OR ISNULL(D.col3, '') <> ISNULL(S.col3,'') 
    OR ISNULL(D.col4, '') <> ISNULL(S.col4,'') 
    OR ISNULL(D.col5, '') <> ISNULL(S.col5,'') 
    OR ISNULL(D.col6, '') <> ISNULL(S.col6,'') 
    OR ISNULL(D.col7, '') <> ISNULL(S.col7,'') 
    OR ISNULL(D.col8, '') <> ISNULL(S.col8,'') 
) 

D.ID или S.ID или D.colx или S.colx также может быть Null

0

INTERSECT and EXCEPT ручки NULL так, как вы хотите. (Т.е. NULL = NULL)

... 
WHEN MATCHED 
    AND EXISTS (SELECT D.Col1, D.Col2, ... 
       EXCEPT S.Col1, S.Col2, ...) 
1

Вы могли бы сделать это намного проще с BINARY_CHECKSUM:

MERGE DestinationTable AS D 
USING SourceTable AS S 
ON D.Alternate_ID = S.ID 
WHEN MATCHED AND 
BINARY_CHECKSUM(d.col1, d.col2, ...,d.col8) <> BINARY_CHECKSUM(s.col1, ..., s.col8) 

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

Смежные вопросы