SQL比较和空值的问题

时间:2013-04-10 14:52:12

标签: sql sql-server-2008

我有一个更新查询,当该值与另一个表中的字段不匹配时,它会更新一个表中的字段。

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

我遇到的问题是,当a.field1为空且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)
            )

我的问题更关注为什么会发生这种情况以及如何最好地构建查询以防止这种情况发生?

8 个答案:

答案 0 :(得分:8)

问题在于NULL比较。如果a.field1或b.field3为NULL,则需要使用IS NULL或IS NOT NULL语句。您可以将a.field1和b.field3的默认值与ISNULL函数一起使用。

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

在这种情况下,与值0进行比较。

SELECT IIF(NULL = NULL,'true','false') - 结果为false。惊人!

答案 1 :(得分:5)

将任何内容与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
              )

答案 2 :(得分:1)

除了正确处理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)
            )

答案 3 :(得分:1)

Tim Shmelter的评论是正确的,NULL并不等于任何事情 - 甚至包括NULLNULL字面意思是价值未知。

这意味着,即使a.field1b.field3都是NULL,条件a.field1 <> b.field3a.field1 = b.field3也将始终返回false。尝试一下,你会看到!

我认为这里的解决方案不在于SQL Server的IFNULL功能。它更多地取决于你的加入逻辑。您已经有了解决方案,即问题中的第二个查询。我建议您使用NULL值进行更多操作,以便了解它们究竟是什么。

答案 4 :(得分:1)

您可以在sql server中使用coalesce将列的值默认为非null值。 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,那么这两行是等价的。

答案 5 :(得分:0)

当你在查询a.field1 = b.field3中写字时,你实际上做了两个假设:表a中的field1必须包含一个值,而b表中的field3也必须包含一个值。无法将“缺失信息和不适用信息”与值进行比较。这种比较的结果是未知的。您可以查看有关Wikipedia的更多信息。

答案 6 :(得分:0)

这将检查Column1和Column2是否相等,另外使用Convertion到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以检查不相等的条件。

希望得到这个帮助。

答案 7 :(得分:0)

另一种方法是使用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