SQL Server与NULL比较

时间:2018-06-18 20:40:06

标签: sql sql-server tsql null

我需要在值和之前的值之间进行大量的比较。

例如:ReceivedByPreviousReceivedBy

我开始时:

WHERE ReceivedBy != PreviousReceivedBy

但是如果任何一个值为null,则返回false,(当我真的需要它为真时)。所以我把它更新为:

WHERE ReceivedBy != PreviousReceivedBy
      OR (ReceivedBy IS NULL AND PreviousReceivedBy IS NOT NULL)
      OR (ReceivedBy IS NOT NULL AND PreviousReceivedBy IS NULL)

这很好用,但我有一大堆需要比较的字段。我想找到一种方法来用较少的代码进行比较(不关闭ANSI_NULLS)。

显然如果没有别的办法,那么我只需要输入所有3行进行比较。

更新:

作为一个例子,这是我希望的

ReceivedBy = 123  
PreviousReceivedBy = 123  
Result = FALSE  

ReceivedBy = 5  
PreviousReceivedBy = 123  
Result = TRUE  

ReceivedBy = NULL  
PreviousReceivedBy = 123  
Result = TRUE

ReceivedBy = 123  
PreviousReceivedBy = NULL  
Result = TRUE  

ReceivedBy = NULL  
PreviousReceivedBy = NULL  
Result = FALSE  

5 个答案:

答案 0 :(得分:2)

如果两列都是varchar s,我会选择以下内容:

coalesce(ReceivedBy, 'NULL') != coalesce(PreviousReceivedBy, 'NULL')

如果它们是整数,我会将一些值大大低于零(以明确表示null值)而不是'NULL'

从列的名称我假设它必须是字符串值或整数值:)

<强>更新

正如@Siyual指出的那样,替换字符串应该是&#34;在可能性范围之内&#34;,你应该将'NULL'替换为一些非字母字符,如'#': )

答案 1 :(得分:2)

另一种不重复数据的方法是使用COALESCE

Where ReceivedBy != PreviousReceivedBy
And Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null

NULL不能等同于任何内容,甚至不能等同于NULL,因此,如果任何值为NULL,则ReceivedBy != PreviousReceivedBy将评估为真。

其次,如果两个值均为NULL,则Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null将评估为false,从而强制对其进行过滤。

如果两者都不是NULL,那么第一个条件如果相等就会失败。

不可否认,这并没有节省太多代码,但这是一种改进。

这可以很容易地分组在括号中,并复制/面食,以便您检查所有剩余的字段。

Where (ReceivedBy != PreviousReceivedBy And Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null)
And[Or] (Foo != Bar And Coalesce(Foo, Bar) Is Not Null)
...

答案 2 :(得分:1)

在与可为空的值进行比较时,我遇到了同样的问题,NULL总是返回unknown,直到我们只在TRUEFALSE之间我们想要的距离为止

最后,我声明了一个标量值函数,这些逻辑像other SQL(s)这样将NULL处理为

普通比较运算符产生null(表示“未知”),而不是 当任一输入为null时为true或false。例如,7 = NULL产生 null,7 <> NULL也是如此。如果此行为不合适,请使用 是[不是]与构造不同:

a IS DISTINCT FROM b => a != b
a IS NOT DISTINCT FROM b => a == b

a IS NOT DISTINCT FROM b could be rewritten

(a IS NOT NULL AND b IS NOT NULL AND a=b) OR (a IS NULL AND b is NULL)

我将sql_variant用于以下基本参数:int,datetime,varchar,...

create function IsEqual(
    @a sql_variant,
    @b sql_variant
)
returns bit
as
begin
    return (CASE WHEN (@a IS NOT NULL AND @b IS NOT NULL AND @a=@b) OR (@a IS NULL AND @b is NULL) THEN 1 ELSE 0 END);
end

create function IsNotEqual(
    @a sql_variant,
    @b sql_variant
)
returns bit
as
begin
    return 1-dbo.IsEqual(@a,@b);
end

使用

select dbo.IsEqual(null, null) Null_IsEqual_Null,
dbo.IsEqual(null, 1) Null_IsEqual_1,
dbo.IsEqual(1, null) _1_IsEqual_Null,
dbo.IsEqual(1, 1)  _1_IsEqual_1,
dbo.IsEqual(CAST('2017-08-25' AS datetime), null) Date_IsEqual_Null,
dbo.IsEqual(CAST('2017-08-25' AS datetime), CAST('2017-08-25' AS datetime)) Date_IsEqual_Date

Result

针对您的情况

select dbo.IsNotEqual(123,123) _123_IsNotEqual_123,
dbo.IsNotEqual(5,123) _5_IsNotEqual_123,
dbo.IsNotEqual(Null,123) Null_IsNotEqual_123,
dbo.IsNotEqual(123,Null) _123_IsNotEqual_Null,
dbo.IsNotEqual(Null,Null) Null_IsNotEqual_Null

enter image description here

答案 3 :(得分:1)

(NULLIF(@a, @b) IS NOT NULL)的意思是"@a != @b,即使其中之一或两者均为空。

答案 4 :(得分:1)

WHERE ISNULL(ReceivedBy, -1) != ISNULL(PreviousReceivedBy, -1)

假设列永远不会有负值