SQL进阶之三值逻辑与NULL
三值逻辑与NULL
越前须知(雾)
- 本系列参考《SQL进阶教程》1,DBMS选用MySQL。
- 本系列不涉及数据库安装与基础语句,对初学者存在一定门槛;基础知识建议阅读《SQL必知必会(第四版)》与《SQL基础教程(第二版)》。
三值逻辑概述
- 普通语言里的布尔型只有 true 和 false 两个值,即二值逻辑;SQL中有 true、false 和 unknown,即三值逻辑;
- 关系模型并不是描述现实世界的模型,而是描述人类认知状态的核心(知识)的模型,我们有限且不完备的知识也会直接反映在表里;
- 三值逻辑优先顺序:
- AND: False > Unknown > True;若AND运算真值为 True,即参与运算的字段条件均为 True;
- OR:True > Unknown > False;
具体应用
简单规则
Q:为什么WHERE co l_1 = NULL 会出错?
A:NULL不是值,只是一个“没有值”的标记,需要用 where col_1 is null;
select * from tbl_A where col_1 = null; -- 结果为空
select * from tbl_A where col_A is null;
Q:排中律在SQL中是否成立?(排中律:一个人年龄要么等于20,要么不等于20)
A:在SQL中,排中律不存在
select *
from Students
where age = 20
or age <> 20; -- 无法查询出年龄为NULL的学生
Q:CASE表达式中,NULL应该怎么写?
A:搜索表达式 + IS NULL
case col_1
when 1 then '〇'
when null then 'x' -- 表达式为 col_1 = NULL,结果为空
end;
case when col_1 = 1 then '〇'
when col_1 is null then 'x'
end;
NOT IN 和 NOT EXISTS 不等价
- 创表
CREATE TABLE Class_A
(name VARCHAR(16) PRIMARY KEY,
age INTEGER,
city VARCHAR(16) NOT NULL );
CREATE TABLE Class_B
(name VARCHAR(16) PRIMARY KEY,
age INTEGER,
city VARCHAR(16) NOT NULL );
INSERT INTO Class_A VALUES('布朗', 22, '东京');
INSERT INTO Class_A VALUES('拉里', 19, '埼玉');
INSERT INTO Class_A VALUES('伯杰', 21, '千叶');
INSERT INTO Class_B VALUES('齐藤', 22, '东京');
INSERT INTO Class_B VALUES('田尻', 23, '东京');
INSERT INTO Class_B VALUES('山田', NULL, '东京');
INSERT INTO Class_B VALUES('和泉', 18, '千叶');
INSERT INTO Class_B VALUES('武田', 20, '千叶');
INSERT INTO Class_B VALUES('石川', 19, '神奈川');
Q:查询“与B班住在东京的学生年龄不同的A班学生”,即“拉里”和“伯杰”
A:不能用NOT IN
- NOT IN:在子查询存在NULL时,查询结果永远为空
- NOT EXISTS:不受子查询中NULL影响
-- NOT IN:结果为空
select *
from Class_A
where age not in (select age
from Class_B as B
where B.city = '东京');
-- NOT EXISTS:不受NULL影响
select *
from Class_A as A
where not exists (select *
from Class_B as B
where A.age = B.age
and B.city = '东京');
限定谓语 (ALL、ANY) 和NULL
Q:ANY相当与IN;ALL和比较谓语联用表示“与所有的XX都相等”、“比所有的XX都大”,若遇到NULL
A:若ANY、ALL遇到NULL,查询结果永远为空
select *
from Class_A as A
where age < all (select age
from Class_B as B
where B.city = '东京');
极值函数 (MAX、MIN) 和NULL
Q:MAX和比较谓语联用表示“比XXX里最大的更大”,若遇到NULL
A:极值函数只对非NULL起作用
- 若少量值为NULL,则MAX表示“比XXX剩下非NULL里最大的更大”;
- 若整个子查询为NULL,则查询结果为空
select *
from Class_A as A
where age < (select min(age)
from Class_B
where city = '东京');
聚集函数 (COUNT、AVG) 和NULL
- 除了COUNT(*),其他聚集函数与极值函数一样,只对非NULL起作用
MICK[日] 《SQL进阶教程》 ↩︎