我的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”评估为“未知”。 NOT(UNKNOWN)仍然是UNKNOWN(msdn),它会强制CASE语句进入ELSE。
但是那时equals-operator的官方文档是错误的。我简直不敢相信!
有人可以解释这种行为吗?
非常感谢您的帮助!
编辑(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-Statement写入'False',但插入运行没有错误。 SQL-Server似乎否定了检查约束,以便搜索不符合约束检查的行:
IF EXISTS (SELECT * FROM inserted WHERE NOT(Value>NULL)) <Generate error>
由于check-constraint的计算结果为UNKNOWN,否则也是UNKNOWN,并且SqlServer没有找到任何违反check-constraint的行。
答案 0 :(得分:6)
是的,链接错误。在Microsoft Connect上提交文档错误。
Sql使用三值逻辑而不是布尔逻辑。 true
,false
和unknown
涉及IS [NOT] NULL
的大多数比较运算符(即不包括NULL
)会导致unknown
而非True
或False
。根据真值表shown here否定未知的未知数。
答案 1 :(得分:5)
您链接到的Equals的MSDN页面肯定显示不正确。
检查SET ANSI_NULLS的MSDN页面。
当SET ANSI_NULLS为ON时,所有与空值的比较 评估为UNKNOWN。
要使该示例SQL语句按预期工作,您应该使用"IS NULL" or "IS NOT NULL"而不是使用equals运算符(=)进行比较。例如:
SELECT CASE WHEN NOT(1 IS NULL) THEN 1 ELSE 0 END
OR
SELECT CASE WHEN (1 IS NOT NULL) THEN 1 ELSE 0 END
答案 2 :(得分:2)
您想阅读documentation on 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
这导致我的计算机上的-1
(SQL Server 2005 Enterprise)。将第一行更改为SET ANSI_NULLS OFF
会按预期生成1
。
那么,官方文档是错误的吗?我认为这有点误导。它说它导致FALSE。显然这是错误的。文档的意思是将非null与NULL进行比较总是会导致不匹配,其值也取决于ANSI_NULLS
。
当然,on SQL Server 2012,ANSI_NULLS
设置已被删除,因此以任何方式设置都不会改变结果。
答案 3 :(得分:2)
这不是布尔逻辑,它的三元逻辑:{真,假,我不知道。}以这种方式分解:
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
,又名“非真”。这可以让你
SELECT CASE WHEN NOT(1=NULL) THEN 1 ELSE 0 END
如上所述与
相同SELECT CASE WHEN NULL THEN 1 ELSE 0 END
,由于NULL
不成立,因此转而使用ELSE
子句。
简而言之,就我而言,文档不正确。令人痛苦,但不是唯一的,所以并不完全令人惊讶。
答案 4 :(得分:0)
尝试在子查询中使用EXISTS,它使用2值逻辑,并为您提供正在寻找的真/假。
答案 5 :(得分:0)
从BOL(信用卡到Thomas):
SET ANSI_NULLS ON仅在其中一个操作数的情况下影响比较 比较是一个NULL变量或文字NULL。如果 比较的两边都是列或复合表达式 设置不会影响比较。
所以我猜NOT
操作正在检查1=NULL
哪个是未知的,因为这不是变量或字面值NULL假设你的比较中有ELSE部分。
答案 6 :(得分:0)
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