SQL Server 与 NULL 比较

Vac*_*ano 6 sql t-sql sql-server null

我需要在一个值和它之前的值之间进行很多比较。

例如:ReceivedByPreviousReceivedBy

我开始于:

WHERE ReceivedBy != PreviousReceivedBy
Run Code Online (Sandbox Code Playgroud)

但是,如果其中一个值为 null,则返回 false,(当我真的需要它为 true 时)。所以我更新它看起来像这样:

WHERE ReceivedBy != PreviousReceivedBy
      OR (ReceivedBy IS NULL AND PreviousReceivedBy IS NOT NULL)
      OR (ReceivedBy IS NOT NULL AND PreviousReceivedBy IS NULL)
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我有大量需要比较的字段列表。我想找到一种方法来用更少的代码(不关闭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  
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyn 5

如果两列都是varchars,我会选择这样的内容:

coalesce(ReceivedBy, 'NULL') != coalesce(PreviousReceivedBy, 'NULL')
Run Code Online (Sandbox Code Playgroud)

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

从列的名称来看,我认为它必须是字符串值还是整数值:)

更新

正如@Siyual 指出的,替换字符串应该“超出可能性范围”,您应该'NULL'用一些非字母字符替换上面的内容,如'#':)

  • 我要指出的是,该值实际上可以是任何东西,并且空检查应该是可能性范围之外的东西。我似乎记得有一家航空公司做过这样的事,然后遇到了一个合法姓氏为“Null”的人。航空公司输了;) (5认同)

Tấn*_*yên 3

在与可为空值进行比较时,我遇到了与您相同的问题,NULL总是返回unknown与我们期望的距离仅在TRUE或之间FALSE

我最终声明了一个带有这些逻辑的标量值函数,就像其他处理 null 的SQL一样

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

a IS DISTINCT FROM b => a != b
a IS NOT DISTINCT FROM b => a == b
Run Code Online (Sandbox Code Playgroud)

可以a IS NOT DISTINCT FROM b 重写

(a IS NOT NULL AND b IS NOT NULL AND a=b) OR (a IS NULL AND b is NULL)
Run Code Online (Sandbox Code Playgroud)

我使用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
Run Code Online (Sandbox Code Playgroud)

使用

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
Run Code Online (Sandbox Code Playgroud)

结果

对于您的情况

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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述