必须用 is null 或 is not null 判断 null,因 = null 恒返回 unknown,if 只响应 true,故分支永远不执行;where 中需用 (@p is null or col = @p) 跳过空参数;计算时须用 coalesce 清洗 null,否则结果静默为 null。

不能用 = NULL 或 != NULL 判断,必须用 IS NULL 或 IS NOT NULL —— 否则条件永远不成立,逻辑静默失效。
存储过程里写 IF @var = NULL 为什么永远进不去分支?
因为 = NULL 在 SQL 中恒返回 UNKNOWN,而 IF 只响应 TRUE;UNKNOWN 和 FALSE 都跳过整个分支。这不是 bug,是三值逻辑的强制行为。
- 错误写法:
IF @status = 'active'→ 当@status是NULL时,整条表达式为UNKNOWN,分支被跳过 - 正确写法:
IF @status IS NULL或IF @status = 'active' OR @status IS NULL(按需) - 在
CASE中同样适用:CASE WHEN @flag IS NULL THEN 'unset' ELSE 'set' END
WHERE 中参数为 NULL 时如何跳过该条件?
常见于可选搜索参数场景。核心思路是把“参数为空”和“应用过滤”拆成两个逻辑分支,用 OR 连接。
- 安全模式:
WHERE (@name IS NULL OR name = @name) AND (@age IS NULL OR age = @age) - 避免写成:
WHERE name = ISNULL(@name, name)—— 表面简洁,但可能使索引失效 - 注意顺序:带
DEFAULT NULL的参数必须放在存储过程参数列表末尾,否则调用时跳过中间参数会报错expects parameter '@p2', which was not supplied
计算或拼接时遇到 NULL 导致结果全为 NULL 怎么办?
NULL 参与算术、字符串连接、比较等操作,结果几乎总是 NULL。这不是意外,是设计如此 —— “未知 + 任何值 = 未知”。
- 数值清洗:
COALESCE(price, 0) * COALESCE(qty, 0),不能只补一个 - 字符串兜底:
COALESCE(first_name, '') + ' ' + COALESCE(last_name, '') - 慎用
IFNULL(MySQL 特有)或ISNULL(SQL Server 特有)——跨库迁移时要重写,COALESCE是标准且支持多参数的首选 - 插入前务必检查:
INSERT INTO log (msg) VALUES (COALESCE(@input_msg, 'N/A')),否则@input_msg为NULL会导致整行插入失败或字段留空
IN/NOT IN 里混入 NULL 为什么查不到数据?
NOT IN (1, 2, NULL) 等价于 col != 1 AND col != 2 AND col != NULL,最后一项恒为 UNKNOWN,整个 AND 结果必为 UNKNOWN,WHERE 直接丢弃。
- 动态拼接时尤其危险:不要直接拼
NOT IN (@list),若@list来自含NULL的表,结果集为空 - 替代方案:
NOT EXISTS (SELECT 1 FROM @temp t WHERE t.val = col AND t.val IS NOT NULL) - 或先清理:
WHERE col NOT IN (SELECT val FROM @temp WHERE val IS NOT NULL)
真正容易被忽略的点不是语法本身,而是 NULL 在不同上下文中的“传染性”:它能让 WHERE 过滤掉整行、让 IF 跳过分支、让 + 得到 NULL、让 NOT IN 返回空集 —— 所有这些行为都一致遵循三值逻辑,但每种场景的修复方式不同,没法靠一个函数一劳永逸。











