知识卡片
避免NULL的实践规则:NOT NULL约束与COALESCE
内容
关系模型禁止NULL,所以要关系化地使用SQL就必须主动堵住所有NULL的入口。第一道
防线是给每张基表的每一列都(显式或隐式)加上NOT NULL约束,这样NULL就不会从
基表源头产生;但一些SQL结构仍会在查询过程中制造出NULL——例如参数为空集合时
的SUM等集函数(COUNT和COUNT(*)除外,它们在空参数下正确返回0)、标量子查询
结果为空表时被型转为NULL、行子查询结果为空表时被型转为全NULL的行、外连接和
“并连接”(union join)设计本身就以产出NULL为目的、省略CASE表达式的ELSE分支
(等价于隐式的ELSE NULL)、x=y为TRUE时NULLIF(x,y)返回NULL,以及ON DELETE
SET NULL/ON UPDATE SET NULL这类参照触发动作。对应的实践清单是:每列都加NOT
NULL;除NOT NULL约束本身外任何地方都不要出现关键字NULL;任何上下文都不要用
UNKNOWN;CASE表达式一定要写ELSE分支;不用NULLIF;不用外连接及OUTER/FULL/LEFT/
RIGHT关键字([[外连接是被null填充的并运算]]例外情形除外);不用”并连接”;不对
MATCH指定PARTIAL/FULL、外键约束不用MATCH选项、不用IS DISTINCT FROM(没有NULL
时它就等价于<>);不用IS TRUE/IS NOT TRUE/IS FALSE/IS NOT FALSE(没有NULL时
这几个判断纯属多余,直接用原表达式或其取反即可);对每个可能”取到NULL”的标量
表达式套一层COALESCE,用一个确定的非NULL值顶替,例如
COALESCE(SUM(ALL SP.QTY),0)确保没有出货记录的供应商得到0而不是NULL(这个
用法同时说明用ALL代替DISTINCT在这种场合不仅可以接受、逻辑上也是必要的)。