什么时候"不"不是否定?

Chr*_*isN 45 t-sql sql-server null evaluation expression

为什么以下两个都返回零?当然第二个是对第一个的否定?我正在使用SQL Server 2008.

DECLARE 
    @a VARCHAR(10) = NULL ,
    @b VARCHAR(10) = 'a'

SELECT  
    CASE WHEN ( ( @a IS NULL
                      AND @b IS NULL
                    )
                    OR @a = @b
                  ) THEN 1
         ELSE 0
    END , -- Returns 0
    CASE WHEN NOT ( ( @a IS NULL
                      AND @b IS NULL
                    )
                    OR @a = @b
                  ) THEN 1
         ELSE 0
    END -- Also returns 0
Run Code Online (Sandbox Code Playgroud)

Lua*_*aan 50

这是一种否定.但是,您需要了解ANSI NULL - NULL的否定也是NULL.而NULL是一个虚假的真值.

因此,如果您的任何参数为null,则结果@a = @b将为null(falsy),并且否定该参数也将为null(falsy).

要以你想要的方式使用否定,你需要摆脱NULL.但是,简单地反转比较结果可能更容易:

case when (...) then 1 else 0 end,
case when (...) then 0 else 1 end
Run Code Online (Sandbox Code Playgroud)

哪个总能给你1, 0或者0, 1.

编辑:

正如jpmc26所指出的那样,对于null的行为方式进行扩展可能会有所帮助,这样你就不会认为单个NULL会产生一切 NULL.null当其中一个参数为null时,有些运算符并不总是返回- is null当然,最明显的例子就是这样.

在一个更广泛的例子中,T-SQL中的逻辑运算符使用Kleene的代数(或类似的东西),它定义了OR表达式的真值,如下所示:

  | T | U | F
T | T | T | T
U | T | U | U
F | T | U | F
Run Code Online (Sandbox Code Playgroud)

(AND和其他运营商一样)

所以你可以看到,如果至少有一个参数为真,那么结果也是真的,即使另一个是未知的("null").这也意味着,not(T or U)会给你一个falsy真值,而not(F or U)会同时给你一个falsy真值,尽管F or U是falsy -因为F or UIS U,和not(U)也U,这是falsy.

这很重要,可以解释为什么当两个参数都为null时,表达式的工作方式与预期方式相同 - @a is null and @b is null计算结果为true,并true or unknown计算结果为true.

  • @NoSaidTheCompiler它表示一个行为类似于false的真值. (2认同)

sag*_*agi 8

您遇到的这种"怪异"行为是由NULL值引起的.

否定NOT (Something that returns NULL)不是TRUE,它仍然存在NULL.

例如

SELECT * FROM <Table> WHERE <Column> = null -- 0 rows 
SELECT * FROM <Table> WHERE NOT (<Column> = null) -- Still 0 rows
Run Code Online (Sandbox Code Playgroud)

除了这里所说的,你可以通过使用来避免这种行为

SET ANSI_NULLS OFF
Run Code Online (Sandbox Code Playgroud)

哪个会让优化器NULL视为正常值,并返回TRUE\FALSE.你应该注意,根本不建议这样做,你应该避免它!