null参与算术运算结果为null,需用coalesce或isnull提前兜底;where中null比较返回unknown被过滤;聚合函数默认忽略null;concat遇null得全包coalesce;select into前须显式置null。

直接说结论:NULL参与任何算术运算都会让结果变成NULL,不是报错,是静默污染——你得在计算前就用COALESCE或ISNULL兜底,而不是事后检查。
存储过程里SET @sum = @sum + @amount突然变NULL了怎么办
这是最典型的静默崩坏:只要@amount是NULL,整条语句执行后@sum立刻变成NULL,后续所有基于它的加减、赋值、判断全失效,但过程不报错、不中断。
- 别写
IF @amount IS NULL SET @amount = 0再运算——多一步就多一个漏判风险 - 统一改用
SET @sum = @sum + COALESCE(@amount, 0)(跨库)或SET @sum = @sum + ISNULL(@amount, 0)(SQL Server专属) - 注意类型一致性:
COALESCE(@amount, 0)中若@amount是DECIMAL(10,2),返回仍是DECIMAL(10,2);而ISNULL(@amount, 0)会强制按@amount类型返回,更稳妥
WHERE条件里@status = 'active'查不到NULL行,但你以为它“不算数”
这不是数据没匹配上,是逻辑根本没跑完:@status = 'active'遇到NULL时返回UNKNOWN,被WHERE当false过滤掉,连ELSE都不进。
- 想查“active或空值”,必须拆开:
WHERE @status IS NULL OR @status = 'active' - 想让NULL也参与等值逻辑,先转换再比:
WHERE COALESCE(@status, 'unknown') = 'active',但注意这会让索引失效 - 更高效的做法是用标志变量预处理:
DECLARE @filter_status VARCHAR(20) = COALESCE(@status, 'unknown'),再在WHERE里用status = @filter_status
SUM/AVG聚合结果和预期对不上,其实是NULL被自动跳过了
SUM(amount)和AVG(amount)天然忽略NULL,但业务上“没填=0”时,统计结果就会偏低——这不是函数错了,是你没告诉它怎么对待缺失值。
- 别依赖
COUNT(amount)去反推NULL数量,直接用COUNT(*) - COUNT(amount) - 需要把NULL当0算总和:
SUM(COALESCE(amount, 0)) - 需要保留NULL语义(比如区分“未发生”和“0元”),就别包
COALESCE,但文档里必须写明聚合逻辑 - 触发器里拼接字符串更要小心:
CONCAT('ID:', id, '-', name)中任一字段为NULL,结果就是NULL,得全用COALESCE包住
选COALESCE还是ISNULL?关键看移植性和参数层数
二者都能兜底,但行为差异直接影响可维护性。一个写错,迁移时可能整段存储过程跑不起来。
-
ISNULL只支持两个参数,SQL Server专用,返回值类型严格继承第一个参数——适合性能敏感且不换库的场景 -
COALESCE支持任意多参数,是ANSI标准,PostgreSQL/MySQL/Oracle全兼容——比如COALESCE(@name, @backup_name, 'unknown')一层写完 - 陷阱:如果写
COALESCE(@date_col, GETDATE(), '1900-01-01'),字面量字符串会尝试转DATETIME,格式不对直接报错;而ISNULL(@date_col, GETDATE())在索引视图里还可能被禁止
最常被忽略的一点:存储过程中SELECT ... INTO @var查不到数据时,@var不会变NULL,而是保持旧值——这意味着你用COALESCE(@var, 0)得到的未必是“默认值”,而是上次残留。务必在SELECT前显式SET @var = NULL。











