知识卡片

避免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在这种场合不仅可以接受、逻辑上也是必要的)。

参考来源

- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第4章"不要重复,不要 null"4.5节"在SQL中避免null"(源文件:OEBPS/text00047.html) - 结论依据:原文明确"应该对每张基表的每列都(显式或隐式地)指定NOT NULL约束 ……对于每个基表的每列都(显式或隐式地)指定NOT NULL……在任何场合下都不要 使用关键字NULL……对于每个可能'得到null'的标量表达式都要使用COALESCE""表达式 COALESCE(a,b,…,c)在其实参全部为null时返回null,否则返回其第一个不为 null的值"。 - 原始内容:应该对每张基表的每列都(显式或隐式地)指定NOT NULL约束……在任何 场合下都不要使用关键字NULL……对于每个可能"得到null"的标量表达式都要使用 COALESCE。