
1. 三值逻辑
1.1. 真
1.2. 假
1.3. 不确定
2. 两种NULL
2.1. 未知”(unknown)
- 2.1.1. 不知道戴墨镜的人眼睛是什么颜色
- 2.1.2. 虽然现在不知道,但加上某些条件后就可以知道
2.2. “不适用”(not applicable,inapplicable)
- 2.2.1. 不知道冰箱的眼睛是什么颜色
- 2.2.2. 在语义上更接近于“无意义”
- 2.2.3. 而不是“不确定”
- 2.2.4. 无论怎么努力都无法知道
2.3. Codd提倡在关系数据库中使用四值逻辑
- 2.3.1. 现在所有的DBMS都将两种类型的NULL归为了一类并采用了三值逻辑
2.4. 数据库里只要存在一个NULL,查询的结果就可能不正确
2.5. 最佳方法应该是往表里添加NOT NULL约束来尽力排除NULL
3. IS NULL
3.1. 谓词
3.2. 对NULL使用比较谓词后得到的结果总是unknown
- 3.2.1. --以下的式子都会被判为 unknown
- 1 = NULL
- 2 > NULL
- 3 < NULL
- 4 <> NULL
- NULL = NULL
复制代码 - 3.2.2. 比较谓词只适用于值
- 3.2.2.1. NULL不是值,所以不能对其使用谓词
3.3. 查询结果只会包含WHERE子句里的判断结果为true的行
- 3.3.1. 不会包含判断结果为false和unknown的行
3.4. NULL既不是值也不是变量
- 3.4.1. NULL只是一个表示“没有值”的标记
- 3.4.2. 因为NULL不是值,所以不在定义域(domain)中
3.5. IS NULL这样的谓词是由两个单词构成的,所以人们容易把IS当作谓词,而把NULL当作值
4. 三值逻辑
4.1. AND的情况: false > unknown > true
4.2. OR的情况: true > unknown > false
5. 排中律
5.1. Law of Excluded Middle
5.2. “把命题和它的否命题通过‘或者’连接而成的命题全都是真命题”这个命题在二值逻辑中被称为排中律
5.3. 在SQL的世界里,排中律是不成立的
5.4. 示例
- 5.4.1. --查询年龄是20岁或者不是20岁的学生
- SELECT *
- FROM Students
- WHERE age = 20
- OR age <> 20;
复制代码 - 5.4.2. --1.约翰年龄是NULL(未知的NULL!
- SELECT *
- FROM Students
- WHERE age = NULL
- OR age <> NULL;
复制代码 - 5.4.3. --2.对NULL使用比较谓词后,结果为unknown
- SELECT *
- FROM Students
- WHERE unknown
- OR unknown;
复制代码 - 5.4.4. --3.unknown OR unknown的结果是unknown
- SELECT *
- FROM Students
- WHERE unknown;
复制代码 - 5.4.5. SQL语句的查询结果里只有判断结果为true的行
- 5.4.5.1. --添加第3个条件:年龄是20岁,或者不是20岁,或者年龄未知
- SELECT *
- FROM Students
- WHERE age = 20
- OR age <> 20
- OR age IS NULL;
复制代码 6. CASE表达式
6.1. 示例
- 6.1.1. --col_1为1时返回○、为NULL时返回×的CASE表达式?
- CASE col_1
- WHEN 1 THEN'○'
- WHEN NULL THEN'×'
- END
复制代码 - 6.1.2. CASE表达式一定不会返回×
- 6.1.2.1. 第二个WHEN子句是col_1 = NULL的缩写形式
- 6.1.3.
- CASE WHEN col_1 = 1 THEN'○'
- WHEN col_1 IS NULL THEN'×'
- END
复制代码 6.2. CASE表达式的判断方法与WHERE子句一样,只认可真值为true的条件
7. NOT EXISTS
7.1. IN改写成EXISTS是等价改写
7.2. NOT IN和NOT EXISTS不是等价的
7.3. 示例
- 7.3.1. B班山田的年龄是NULL
- 7.3.2. --查询与B班住在东京的学生年龄不同的A班学生的SQL语句?
- SELECT *
- FROM Class_A
- WHERE age NOT IN ( SELECT age
- FROM Class_B
- WHERE city =’东京’);
复制代码
- 7.3.3. --正确的SQL语句:拉里和伯杰将被查询到
- SELECT *
- FROM Class_A A
- WHERE NOT EXISTS ( SELECT *
- FROM Class_B B
- WHERE A.age = B.age
- AND B.city = ’东京’);
复制代码 - 7.3.4. --1.执行子查询,获取年龄列表
- SELECT *
- FROM Class_A
- WHERE age NOT IN (22, 23, NULL);
复制代码
- 7.3.4.1. --1.在子查询里和NULL进行比较运算
- SELECT *
- FROM Class_A A
- WHERE NOT EXISTS ( SELECT *
- FROM Class_B B
- WHERE A.age = NULL
- AND B.city =’东京’);
复制代码 - 7.3.5. --2.用NOT和IN等价改写NOT IN
- SELECT *
- FROM Class_A
- WHERE NOT age IN (22, 23, NULL);
复制代码
- 7.3.5.1. --2.对NULL使用“=”后,结果为 unknown
- SELECT *
- FROM Class_A A
- WHERE NOT EXISTS ( SELECT *
- FROM Class_B B
- WHERE unknown
- AND B.city =’东京’);
复制代码 - 7.3.6. --3.用OR等价改写谓词IN
- SELECT *
- FROM Class_A
- WHERE NOT ( (age = 22) OR (age = 23) OR (age = NULL) );
复制代码
- 7.3.6.1. --3.如果AND运算里包含unknown,结果不会是true
- SELECT *
- FROM Class_A A
- WHERE NOT EXISTS ( SELECT *
- FROM Class_B B
- WHERE false或unknown);
复制代码 - 7.3.7. --4.使用德·摩根定律等价改写
- SELECT *
- FROM Class_A
- WHERE NOT (age = 22) AND NOT(age = 23) AND NOT (age = NULL);
复制代码
- 7.3.7.1. --3.如果AND运算里包含unknown,结果不会是true
- SELECT *
- FROM Class_A A
- WHERE NOT EXISTS ( SELECT *
- FROM Class_B B
- WHERE false或unknown);
复制代码
- 7.3.7.2. 山田被作为“与任何人的年龄都不同的人”来处理了
- 7.3.8. --5.用<>等价改写NOT和=
- SELECT *
- FROM Class_A
- WHERE (age <> 22) AND (age <> 23) AND (age <> NULL);
复制代码 - 7.3.9. --6.对NULL使用<>后,结果为unknown
- SELECT *
- FROM Class_A
- WHERE (age <> 22) AND (age <> 23) AND unknown;
复制代码 - 7.3.10. --7.如果AND运算里包含unknown,则结果不为true
- SELECT *
- FROM Class_A
- WHERE false或unknown;
复制代码 7.4. EXISTS谓词永远不会返回unknown
- 7.4.1. EXISTS只会返回true或者false
8. ALL谓词
8.1. 多个以AND连接的逻辑表达式的省略写法
8.2. 与IN是等价的,所以我们不经常使用ANY
8.3. 示例
- 8.3.1. --查询比B班住在东京的所有学生年龄都小的A班学生
- SELECT *
- FROM Class_A
- WHERE age < ALL ( SELECT age
- FROM Class_B
- WHERE city =’东京’);
复制代码
- 8.3.1.1. 他的年龄比在东京住的所有学生都小
- 8.3.2.
- --1.执行子查询获取年龄列表
- SELECT *
- FROM Class_A
- WHERE age < ALL ( 22, 23, NULL );
- --2.将ALL谓词等价改写为AND
- SELECT *
- FROM Class_A
- WHERE (age < 22) AND (age < 23) AND (age < NULL);
- --3.对NULL使用“<”后,结果变为 unknown
- SELECT *
- FROM Class_A
- WHERE (age < 22) AND (age < 23) AND unknown;
- --4. 如果AND运算里包含unknown,则结果不为true
- SELECT *
- FROM Class_A
- WHERE false 或 unknown;
复制代码 9. 极值函数
9.1. --查询比B班住在东京的年龄最小的学生还要小的A班学生- SELECT *
- FROM Class_A
- WHERE age < ( SELECT MIN(age)
- FROM Class_B
- WHERE city =’东京’);
复制代码
- 9.1.1. 他的年龄比在东京住的年龄最小的学生还要小
9.2. 限定谓词和极值函数不是等价的
9.3. 极值函数在统计时会把为NULL的数据排除掉
9.4. 极值函数在输入为空表(空集)时会返回NULL
- 9.4.1.
- --1.极值函数返回NULL
- SELECT *
- FROM Class_A
- WHERE age < NULL;
- --2.对NULL使用“<”后结果为 unknown
- SELECT *
- FROM Class_A
- WHERE unknown;
复制代码 10. 聚合函数
10.1. COUNT以外的聚合函数当输入为空表时返回NULL
10.2. 示例
- 10.2.1. --查询比住在东京的学生的平均年龄还要小的A班学生的SQL语句?
- SELECT *
- FROM Class_A
- WHERE age < ( SELECT AVG(age)
- FROM Class_B
- WHERE city =’东京’);
复制代码 - 10.2.2. 没有住在东京的学生时,AVG函数返回NULL
- 10.2.3. 外侧的WHERE子句永远是unknown,也就查询不到行
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |