t-sql:内置布尔函数之间的不兼容性

时间:2013-04-18 11:07:34

标签: sql-server tsql

为什么内置布尔函数在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

似乎ISDATEISNUMERIC根据布尔逻辑行事,但IS_MEMBERIS_SRVROLEMEMBER - 根据Three valued logic行事。 不应该所有布尔函数在NULL输入上表现相同吗? ANSI SQL标准对此有何看法?

由于

2 个答案:

答案 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中非常适用于所有这些含义。

更具体地说,对于ISNUMERICISDATE的参数,如果参数为null,则可以提前测试,所以我不确定是否需要返回null ,或具有很大的实用性。

对于安全函数的参数,您可能有非null参数,但是在参数无效,未找到或者您没有参数的情况下,函数已经以有用的方式构建以返回null有权知道答案。

其中大部分当然可以被视为主观的,因此我投票决定关闭这个问题,无论它有多么有趣。