为什么内置布尔函数在NULL
输入上表现不同?
例如 - 此查询:
select 'ISDATE(null)' as function_call,
ISDATE(null) as result union all
select 'ISNUMERIC(null)' as function_call,
ISNUMERIC(null) as result union all
select 'IS_MEMBER(null)' as function_call,
IS_MEMBER(null) as result union all
select 'IS_SRVROLEMEMBER(null, null)' as function_call,
IS_SRVROLEMEMBER(null, null) as result
给我们:
function_call result
---------------------------- -----------
ISDATE(null) 0
ISNUMERIC(null) 0
IS_MEMBER(null) NULL
IS_SRVROLEMEMBER(null, null) NULL
似乎ISDATE
,ISNUMERIC
根据布尔逻辑行事,但IS_MEMBER
,IS_SRVROLEMEMBER
- 根据Three valued logic行事。
不应该所有布尔函数在NULL输入上表现相同吗? ANSI SQL标准对此有何看法?
由于
答案 0 :(得分:3)
Re ANSI标准,后两个函数与ANSI SQL无关;它们是MSSQL特定的安全功能。这并不是说他们在其他DBMS中没有类似物,只是因为它们不是“典型的”UML风格函数或标准的一部分。
我事实上,在this reasonably authoritative O'Reilly page上搜索术语“布尔”的ANSI标准函数不会返回任何结果。可以从中推断出这种标量函数对NULL的处理没有ANSI方法。
这些函数中需要三值逻辑,以允许NULL表示输入不是有效。例如,请参阅MSDN IS_MEMBER()
的备注部分。
(这种形式的NULL返回不要与可能返回值的聚合函数混淆,如果其中一个输入为NULL,则为NULL。)
没有什么可以阻止你“包装”这些功能,使其像其他功能一样,如果那是你真正需要的。例如ISNULL(IS_MEMBER(someValueFromATable),0)
。
前两个函数返回一个有意义的布尔值,如您所见。
例如, ISDATE(null)
返回false,因为null 不“有效日期,时间或日期时间值 ” (MSDN,我强调值)。
在将NULL解释为“未知”的情况下,当输入未知时,ISDATE()
等在返回“未知”时具有语义意义,但在编程上不实用;当我们已经为ISNULL()
进行单独的非特定类型测试时,将结果(从所有这些布尔函数)“转换”为从三态到布尔逻辑的需要是完全多余的。
在比较你已经识别的两种类型的函数时,后者的返回值在这种情况下不应该为NULL,因为虽然NULL不是日期,但它仍然是有效的可以通过此功能正确检查的数据。
答案 1 :(得分:0)
我不觉得奇怪的是这些安全函数(IS_SRVROLEMEMBER
)的行为与系统/数据类型函数(ISNUMERIC
)不同,因为这些安全函数本质上是查询,结果可能会根据谁在查询。返回值的含义(包括空值)在MSDN Documentation中非常适用于所有这些含义。
更具体地说,对于ISNUMERIC
和ISDATE
的参数,如果参数为null,则可以提前测试,所以我不确定是否需要返回null ,或具有很大的实用性。
对于安全函数的参数,您可能有非null参数,但是在参数无效,未找到或者您没有参数的情况下,函数已经以有用的方式构建以返回null有权知道答案。
其中大部分当然可以被视为主观的,因此我投票决定关闭这个问题,无论它有多么有趣。