SQL比较和空值问题

SQL比较和空值问题,sql,sql-server-2008,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 更新表1 设置a.field1=b.field3 从表1 a中, 表2 b 其中a.field2=b.field2 和a.field

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

UPDATE  table1
SET     a.field1 = b.field3
FROM    table1 a ,
        table2 b
WHERE   a.field2 = b.field2
        AND a.field1 <> b.field3
更新表1
设置a.field1=b.field3
从表1 a中,
表2 b
其中a.field2=b.field2
和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)
            )
更新表1
设置a.field1=b.field3
从表1 a中,
表2 b
其中a.field2=b.field2
和(a.field1 b.field3
或(a.field1不为空
b.field3为空)
或(a.field1为空)
和b.field3不为空)
)

我的问题更集中于为什么会发生这种情况,以及如何最好地构造查询以防止出现这种情况?

除了正确处理空逻辑之外,还需要将要一起应用的多个条件括在括号中

类似这样的事情(我不确定我是否完全理解你的情况)

更新表1
设置a.field1=b.field3
从表1 a中,
表2 b
其中a.field2=b.field2
及(
(a.field1 b.field3)
或(a.field1不为空,b.field3为空)
或(a.field1为空,b.field3不为空)
)

蒂姆·施梅尔特的评论是正确的,
NULL
不等于任何东西,甚至包括
NULL
NULL
字面意思是该值未知

这意味着,即使
a.field1
b.field3
都是
NULL
,条件
a.field1 b.field3
以及
a.field1=b.field3
都将始终返回false。试试看,你就会明白


我认为这里的解决方案不在于SQL Server的
IFNULL
函数。这更多地取决于你的加入逻辑。您已经有了解决方案,即问题中的第二个查询。我建议您多使用
NULL
值,这样您就可以了解它们的真正含义。

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

ISNULL(a.field1,0) <> ISNULL(b.field3,0)
ISNULL(a.field1,0)ISNULL(b.field3,0)
在本例中,存在与值0的比较


选择IIF(NULL=NULL,'true','false')——结果为false。太棒了

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

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

这将检查Column1和Column2是否相等,另外还使用了到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
您可以将表达式的结尾更改为
不为NULL
,以检查不相等条件


希望有此帮助。

您可以在sql server中使用coalesce将列的值默认为非空值。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)
        )
更新表1
设置a.field1=b.field3
从表1 a中,
表2 b
其中a.field2=b.field2
及(
聚结(a.field1,-1)聚结(b.field3,-1)
)

我假设您的类型是number,但您可以使用其他数据类型。我还假设,如果两个值都为NULL,那么这两行是等效的。

另一种方法是使用函数

create table#temp
(
val1 varchar(255),
val2 varchar(255)
)
插入#临时值(空,空)
插入到#临时值中(NULL,'B')
插入#临时值('A',NULL)
插入#临时值('A'、'B')
插入#临时值('A','A'))
选择*,
“不相等”=大小写
当val1 val2或校验和(val1)校验和(val2)时,则为“真”
否则“假”结束
从#temp

Null等于零,它是一个未定义的值,无法与任何值进行比较(即使使用
)。这就是空值记录被省略的原因。因此,您必须明确地使用
IS NULL
IS NOT NULL
。我最近遇到了“相反”的问题。有人向我提供了一个SQL语句,其中包含了一个比较,比如
其中val=null…
,它在我们的SQL server上的实际工作与
中val为null的情况相同
!事实证明,在我们的服务器上激活了一个设置
SET ANSI_NULLS OFF
。此设置(已弃用!!)可启用空比较,请参阅。谢谢…我在示例中省略了paren,但它们在我的代码中…我已进行了编辑,以便更清楚地了解我所阅读的内容,ifnull几乎需要出现在任何比较查询中?@Rachcha-小更正:如果a.field1或b.field3中的一个(或两个)为空,条件a.field1 b.field3和a.field1=b.field3不会返回FALSE,而是返回NULL。在大多数情况下,它会表现为FALSE(像这个),因为它不是TRUE,但它仍然不是FALSE,也就是说,不能被否定为TRUE。如果你把NOT放在前面(a.field1=b.field3),它仍然是空的,表现得像FALSE。这是一个非常有用的注释。看起来你已经玩了很多空的游戏@希瑟:(选择)而不是过滤(在哪里)。@Norberto108:如果“它[似乎]起作用”,那么它并不意味着是一个“好的]解决方案”。如果
a.field1=0,b.field3为空,该怎么办
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)
        )
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