三值逻辑及NULL一点延伸

三值逻辑及NULL一点延伸

 

flystone           2010-10-29于唐山

 

 

关键词:三值、逻辑、three-valued logic、NULL

 

    今天我们来说说SQL的一个重要特性:三值逻辑。我们一般知道一个表达式的值可能是TRUE或FALSE,SQL引入另一个可能的值UNKNOWN。TRUE、FALSE、UNKNOWN称为三值逻辑,它是SQL的一个重要特性,正常理解是熟练操作SQL的一个条件。

    在SQL的连接操作及搜索数据时使用聚合函数时,我们要注意三值逻辑的微妙之处,处理好三值逻辑还得提到一个关键点NULL值。在SQL中UNKNOWN值一般和NULL有关,也就是UNKNOWN值一般出现在包含在有NULL参与的表式中,在这儿大家一定要分清UNKNOWN作为表达式的值与NULL不是一个意思,不要混淆概念。下面概括为三个方面来说说这个话题。

 

一、包含NULL的表达式值(UNKNOWN)

SELECT

    CASE WHEN NULL = NULL THEN 0 WHEN NULL > NULL THEN 1 WHEN NULL < NULL THEN -1 ELSE -99 END,  

    CASE WHEN NULL IS NULL THEN 1 ELSE 0 END,

    CASE WHEN NULL = 1 THEN 1 ELSE 0 END,

    CASE WHEN NULL > 1 THEN 1 ELSE 0 END,   

    CASE WHEN NULL IS NOT NULL THEN 1 ELSE 0 END,

    CASE WHEN NULL +1 > NULL THEN 1 ELSE 0 END,

    CASE WHEN NULL +1 > 1 THEN 1 ELSE 0 END

   

/*                                                                         

--------- --------- --------- --------- --------- --------- ---------

-99           1           0           0           0           0           0

(1 行受影响)

*/

二、三值的反逻辑

not true => false

not false => true

not unknown => unknown

三、三值逻辑中的UNKNOWN在不同逻辑处理阶段的体现

在查询筛选器、约束、分组、排序中包含NULL的表达的UNKNOWN值SQL会分别对待,下面我们稍加详细说明一下,更的情况我们可以自己写SQL测试。

ON、WHERE、HAVING查询筛选器UNKNOWN被当FALSE处理,也就是被排除在查询的结果之外的。

CHECK约束中UNKNOWN被当作TRUE来处理的。

下面我就CHECK约束来举一个例子,在下例中我在AGE列上加了一个0-99的约束,第一条SQL插入NULL,NULL和INT值比较表达式的值应该是UNKNOWN,但是在CHECK约束中被当TRUE来对待了。

 

---------------------------------------------------------------------

-- Author :flystone

-- Date   : 2010-11-04

-- Version: Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (Intel X86)

--          Mar 29 2009 10:27:29

--          Copyright (c) 1988-2008 Microsoft Corporation

--          Enterprise Edition on Windows NT 5.2 <X86>(Build 3790: SP2)

--     

---------------------------------------------------------------------

CREATE TABLE TA(ID INT,AGE INT CHECK(AGE BETWEEN 1 AND 99))

GO

INSERT INTO TA(ID ) SELECT 1

/*

(1 行受影响)

*/

GO

INSERT INTO TA  SELECT 1,-1

/*

消息547,级别16,状态0,第1 行

INSERT 语句与CHECK 约束"CK__TA__AGE__25869641"冲突。该冲突发生于数据库"CSDN2008",表"DBO.TA", COLUMN 'AGE'。

*/

GO

SELECT * FROM TA

 

/*

ID          AGE

----------- -----------

1           NULL

*/

DROP TABLE TA

    最后在UNIQUE约束、分组或排序中,包含NULL列值比较时,表达式的值被当作TRUE看待,关于这一点我们应该很好理解,比如在排序时所有NULL排在一起,分组时NULL的值汇总在一起,包含UNIQUE约束的列是不能插入两行NULL值的,这些我们都可以写SQL来检测,在这儿不一一列举。

 

因为NULL的参与引入的UNKNOWN值使得我们在处理表达值时必须严谨,否则引起意想不到结果。在这儿我又想在引擎中提到表结构时,这个NULL引起的纷争,就是关于列是否允许为空的问题,正反两方各有各的理由,似乎很难做出一个错或对的判断,不过我们一定可以清醒的意识到,NULL值的处理必然会增加引擎的复杂度,因为我们知道SQL通过bitmap来管理行的记录是否有空值,如果有列允许为NULL,那么在访问每一行时都必须对bitmap进行解码,显然会增加引擎的复杂度,所以严谨些个人还是赞同对所有的列加上缺省并指定为NOT NULL。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值