T-SQL: What is NOT(1=NULL)?



我的sql server上没有简单的布尔代数。根据msdn,下面的语句应该返回"1",但在我的服务器上它返回"0"。你能帮我吗?

SET ANSI_NULLS ON
SELECT CASE WHEN NOT(1=NULL) THEN 1 ELSE 0 END

请看一看msdn。它清楚地指出:"将NULL值与非NULL值进行比较总是会导致FALSE。"-无论ANSI_NULLS设置是什么。因此,"1=NULL"应该是FALSE,NOT(FALSE)应该是TRUE,语句应该返回"1"。

但在我的机器上,它返回"0"!

一种解释可能是,"1=NULL"的计算结果为"UNKNOWN"。NOT(UNKNOWN)仍然是UNKNOWN(msdn),这将强制CASE语句进入ELSE。

但是,平等经营者的官方文件是错误的。我简直不敢相信!

有人能解释这种行为吗?

非常感谢您的帮助!

编辑(2012-03-15):

我刚刚发现你们中的一些人可能感兴趣的一件事:

CREATE TABLE #FooTest (Value INT)
ALTER TABLE #FooTest WITH CHECK ADD CONSTRAINT ccFooTestValue CHECK (Value>1)
PRINT '(NULL>1) = ' + CASE WHEN NULL>1 THEN 'True' ELSE 'False' END
INSERT INTO #FooTest (Value) VALUES (NULL)

print语句写入"False",但插入操作不会出错。SQL Server似乎否定了检查约束,以便搜索不满足约束检查的行:

IF EXISTS (SELECT * FROM inserted WHERE NOT(Value>NULL)) <Generate error>

由于检查约束的计算结果为UNKNOWN,因此否定也是UNKNOWN,并且SqlServer未发现任何违反检查约束的行。

是的,链接是错误的。在Microsoft Connect上提交文档错误。

Sql使用三值逻辑而不是布尔逻辑。truefalseunknown

涉及NULL的大多数比较运算符(即不包括IS [NOT] NULL)导致unknown而不是TrueFalse。根据这里显示的真值表,否定未知会产生未知。

您链接到的用于Equals的MSDN页面肯定不正确。

请查看MSDN页面中的SET ANSI_NULLS。

当SET ANSI_NULLS为ON时,所有与空值的比较评估为未知。

为了使该示例SQL语句按预期工作,您应该使用compare,使用"IS NULL"或"IS NOT NULL",而不是使用equals运算符(=)。例如:

SELECT CASE WHEN NOT(1 IS NULL) THEN 1 ELSE 0 END

SELECT CASE WHEN (1 IS NOT NULL) THEN 1 ELSE 0 END

您想要阅读ANSI_NULLS上的文档。SQL实际上实现了一个三元逻辑,而不是布尔逻辑,其中比较操作可能导致true、false或undefined。基本上,这意味着你提供的解释是正确的。

这可以通过以下查询来证明:

SET ANSI_NULLS ON
SELECT CASE
  WHEN (1=NULL) THEN 0
  WHEN NOT(1=NULL) THEN 1    
  ELSE -1
END

这将在我的计算机(SQL Server 2005 Enterprise)上生成-1。将第一行更改为SET ANSI_NULLS OFF会产生预期的1

那么,官方文件有错吗?我认为这有点误导。它说它的结果是假的。显然这是错误的。文档的意思是,将非null与null进行比较总是会导致不匹配,其值也取决于ANSI_NULLS

当然,在SQL Server 2012上,ANSI_NULLS设置已被删除,因此以任何方式设置都不会更改结果。

它不是布尔逻辑,而是三元逻辑:{True,False,I Don't Know。}按以下方式分解:

IF 1=NULL
    print 'True'
else
    print 'False'

生成False,因为1=NULL等于NULL,也称为"非真"

IF not(1=NULL)
    print 'True'
else
    print 'False'

也会生成False,因为not(1=NULL)等于not(NULL)等于NULL,也就是"not True"。这会让你进入

SELECT CASE WHEN NOT(1=NULL) THEN 1 ELSE 0 END

如上所述与相同

SELECT CASE WHEN NULL THEN 1 ELSE 0 END

由于NULL不为真,因此它适用于ELSE子句。

简而言之,就我而言,这些文件是不正确的。令人沮丧,但不是唯一的,因此也不完全令人惊讶。

尝试在子查询中使用EXISTS,它使用2值逻辑,并将为您提供所需的true/false。

来自BOL(归功于Thomas):

只有当的某个操作数比较要么是NULL变量,要么是文本NULL。如果比较的两边都是列或复合表达式设置不会影响比较。

所以我猜NOT操作是在检查1=NULL,这是未知的,因为这不是一个变量或字面意义上的NULL得到了您假设的比较的ELSE部分。

1=NULL似乎只有在ANSI_NULLS为OFF时才会返回FALSE。否则它是不确定的。可能需要对msdn页面进行编辑以澄清这一点。

SET ANSI_NULLS OFF
SELECT CASE WHEN (1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
, CASE WHEN NOT(1=NULL) THEN 'true' ELSE 'false or unknown' END --returns true
go
SET ANSI_NULLS ON
SELECT CASE WHEN (1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
, CASE WHEN NOT(1=NULL) THEN 'true' ELSE 'false or unknown' END --returns false or unknown
go

相关内容

  • 没有找到相关文章

最新更新