Подтвердить что ты не робот

Проблемы с сопоставлением SQL и значениями null

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

UPDATE  table1
SET     a.field1 = b.field3
FROM    table1 a ,
        table2 b
WHERE   a.field2 = b.field2
        AND a.field1 <> b.field3

Проблема, с которой я сталкиваюсь, заключается в том, что она не поднимается, когда a.field1 имеет значение null, а b.field3 - это значение ИЛИ, если a.field1 является значением, а b.field3 является нулевым.

Я обошел это, добавив следующее...

UPDATE  table1
SET     a.field1 = b.field3
FROM    table1 a ,
        table2 b
WHERE   a.field2 = b.field2
        AND ( a.field1 <> b.field3
              OR (a.field1 IS NOT NULL
              AND b.field3 IS NULL)
              OR (a.field1 IS NULL
              AND b.field3 IS NOT NULL)
            )

Мой вопрос более сосредоточен вокруг того, почему это происходит и как лучше структурировать запрос, чтобы предотвратить это?

4b9b3361

Ответ 1

Проблема заключается в сравнении NULL. Если поле a.field1 или b.field3 равно NULL, вам нужно использовать оператор IS NULL или NOT NOT. Вы можете использовать значение по умолчанию для a.field1 и b.field3 с помощью функции ISNULL.

ISNULL(a.field1,0) <> ISNULL(b.field3,0)

в этом случае происходит сравнение со значением 0.

Ответ 2

Результат сравнения чего-либо с NULL, даже сам по себе, всегда равен NULL (не TRUE или FALSE). Используйте опцию с операторами EXISTS и EXCEPT.

UPDATE table1
SET a.field1 = b.field3
FROM table1 a JOIN table2 b ON a.field2 = b.field2
WHERE EXISTS (
              SELECT a.field1
              EXCEPT
              SELECT b.field3
              )

Ответ 3

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

Что-то вроде этого (не уверен, что я точно понял ваши условия).

UPDATE  table1
SET     a.field1 = b.field3
FROM    table1 a ,
        table2 b
WHERE   a.field2 = b.field2
        AND (
              ( a.field1 <> b.field3)
              OR (a.field1 IS NOT NULL AND b.field3 IS NULL)
              OR (a.field1 IS NULL AND b.field3 IS NOT NULL)
            )

Ответ 4

Тим Шмельтер прав в своем комментарии, NULL не равен чему-либо, даже включая NULL. NULL буквально означает, что значение неизвестно.

Это означает, что даже если a.field1 и b.field3 оба являются NULL, условия a.field1 <> b.field3, а также a.field1 = b.field3 оба всегда будут возвращать false. Попробуйте, и вы увидите!

Я думаю, что решение здесь не лежит в функции IFNULL SQL Server. Это больше связано с вашей логикой присоединения. У вас уже есть ваше решение, т.е. Второй запрос в вашем вопросе. Я порекомендую вам немного больше с NULL значениями, чтобы вы могли понять, что на самом деле они.

Ответ 5

Вы можете использовать coalesce в sql-сервере, чтобы по умолчанию значение столбца равнялось ненулевому значению. Coalesce возвращает первое ненулевое значение в списке.

UPDATE  table1
SET     a.field1 = b.field3
FROM    table1 a ,
        table2 b
WHERE   a.field2 = b.field2
        AND (
           coalesce(a.field1,-1) <> coalesce(b.field3, -1)
        )

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

Ответ 6

Когда вы пишете в своем запросе a.field1 = b.field3, вы фактически делаете два предположения: поле1 в таблице a должно содержать значение, а поле3 в вашей таблице b также должно содержать значение. Невозможно сравнить "недостающую информацию и неприменимую информацию" со значением. Результат этого сравнения неизвестен. Вы можете найти дополнительную информацию о Wikipedia.

Ответ 7

Это будет проверять, равны ли столбцы1 и столбцы2, а также использовать Convertion to VARBINARY для сравнения в случае чувствительности, и вы можете удалить его, если это не необходимо.

--c1 = Length of Column1
--c2 = Length of Column2

ISNULL(NULLIF(CONVERT(VARBINARY(cl), LTRIM(RTRIM(Column1))), CONVERT(VARBINARY(c2),LTRIM(RTRIM(Column2)))), NULLIF(CONVERT(VARBINARY(c2),LTRIM(RTRIM(Column2))), CONVERT(VARBINARY(c1),LTRIM(RTRIM(Column1))))) IS NULL

Вы можете изменить конец выражения на IS NOT NULL для проверки неравного состояния.

Надеюсь на эту помощь.

Ответ 8

Другим способом было бы использовать функцию CHECKSUM

create table #temp
  (
    val1 varchar(255),
    val2 varchar(255)
  )

  insert into #temp values(NULL, NULL) 
  insert into #temp values(NULL, 'B') 
  insert into #temp values('A', NULL) 
  insert into #temp values('A', 'B') 
  insert into #temp values('A', 'A') 

  select *, 
  'Are Not Equal' = case 
   when val1 <> val2 or checksum(val1) <> checksum(val2) then 'true' 
   else 'false' end 
  from #temp