加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

搞清这些陷阱,NULL和三值逻辑再也不会作妖

发布时间:2019-11-11 11:12:22 所属栏目:编程 来源:youzhibing2904
导读:NULL NULL 用于表示缺失的值或遗漏的未知数据,不是某种具体类型的值。数据表中的 NULL 值表示该值所处的字段为空,值为 NULL 的字段没有值,尤其要明白的是:NULL 值与 0 或者空字符串是不同的。 两种NULL 这种说法大家可能会觉得很奇怪,因为 SQL 里只存

记住这个顺序后就能更方便地进行三值逻辑运算了。特别需要记住的是,当 AND 运算中包含 unknown 时,结果肯定不会是 true (反之,如果AND 运算结果为 true ,则参与运算的双方必须都为 true )。

  1. -- 假设 a = 2, b = 5, c = NULL,下列表达式的逻辑值如下 
  2.  
  3. a < b AND b > c  → unknown 
  4. a > b OR b < c   → unknown 
  5. a < b OR b < c   → true 
  6. NOT (b <> c)     → unknown 

“IS NULL” 而非 “= NULL”

我们再回到问题:为什么必须写成“IS NULL”,而不是“= NULL”?

对 NULL 使用比较谓词后得到的结果总是 unknown 。而查询结果只会包含 WHERE 子句里的判断结果为 true 的行,不会包含判断结果为 false 和 unknown 的行。不只是等号,对 NULL 使用其他比较谓词,结果也都是一样的。

所以无论 remark 是不是 NULL ,比较结果都是 unknown ,那么永远没有结果返回。以下的式子都会被判为 unknown:

-- 以下的式子都会被判为 unknown

  1. -- 以下的式子都会被判为 unknown 
  2. = NULL 
  3. > NULL 
  4. < NULL 
  5. <> NULL 
  6. NULL = NULL 

那么,为什么对 NULL 使用比较谓词后得到的结果永远不可能为真呢?

这是因为,NULL 既不是值也不是变量。NULL 只是一个表示“没有值”的标记,而比较谓词只适用于值。

因此,对并非值的 NULL 使用比较谓词本来就是没有意义的。“列的值为 “NULL ”、“NULL 值” 这样的说法本身就是错误的。因为 NULL不是值,所以不在定义域(domain)中。

相反,如果有人认为 NULL 是值,那么我们可以倒过来想一下:它是什么类型的值?关系数据库中存在的值必然属于某种类型,比如字符型或数值型等。所以,假如 NULL 是值,那么它就必须属于某种类型。

NULL 容易被认为是值的原因有两个。

第一个是高级编程语言里面,NULL 被定义为了一个常量(很多语言将其定义为了整数0),这导致了我们的混淆。但是,SQL 里的 NULL 和其他编程语言里的 NULL 是完全不同的东西。

第二个原因是,IS NULL 这样的谓词是由两个单词构成的,所以我们容易把 IS 当作谓词,而把 NULL 当作值。特别是 SQL 里还有 IS TRUE 、IS FALSE 这样的谓词,我们由此类推,从而这样认为也不是没有道理。但是正如讲解标准 SQL 的书里提醒人们注意的那样,我们应该把 IS NULL 看作是一个谓词。因此,写成 IS_NULL 这样也许更合适。

温柔的陷阱

比较谓词和 NULL

排中律不成立。排中律指同一个思维过程中,两个相互矛盾的思想不能同假,必有一真,即“要么A要么非A”。

假设我们有学生表:t_student:

  1. DROP TABLE IF EXISTS t_student; 
  2. CREATE TABLE t_student ( 
  3.     id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', 
  4.     name VARCHAR(50) NOT NULL COMMENT '名称', 
  5.     age INT(3) COMMENT '年龄', 
  6.     remark VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注', 
  7.     primary key(id) 
  8. ) COMMENT '学生信息'; 
  9.  
  10. INSERT INTO t_student(name, age) 
  11. VALUE('zhangsan', 25),('wangwu', 60),('bruce', 32),('yzb', NULL),('boss', 18); 
  12.  
  13. SELECT * FROM t_student; 

表中数据 yzb 的 age 是 NULL,也就是说 yzb 的年龄未知。在现实世界里,yzb 是 20 岁,或者不是 20 岁,二者必居其一,这毫无疑问是一个真命题。那么在 SQL 的世界里了,排中律还适用吗? 我们来看一个 SQL :

  1. SELECT * FROM t_student 
  2. WHERE age = 20 OR age <> 20; 

咋一看,这不就是查询表中全部记录吗?我们来看下实际结果:

搞清这些陷阱,NULL和三值逻辑再也不会作妖

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读