必须用is null判断null,因null是未知状态而非值,=null恒返回unknown,if和where只响应true;正确写法为if @var is null或where col is null。

因为SQL用的是三值逻辑,= NULL永远不返回TRUE,IF分支只响应TRUE,所以直接比较会静默跳过。
IF @var = NULL 为什么永远不进分支
这不是bug,是SQL标准行为:NULL不是值,而是“未知”状态。任何与NULL的等值比较(包括= NULL、!= NULL、@var IN ('a', 'b'))结果都是UNKNOWN,而IF语句只执行判定为TRUE的分支,UNKNOWN和FALSE都被忽略。
- 错误写法:
IF @status = 'active' THEN ... END IF→ 当@status是NULL时,整条表达式为UNKNOWN,分支完全不执行 - 正确写法:
IF @status IS NULL THEN ...或IF @status = 'active' OR @status IS NULL THEN ...(按业务是否需包含空值) - 在
CASE中同理:CASE WHEN @flag IS NULL THEN 'unset' ELSE 'set' END
WHERE中参数为NULL时如何避免条件失效
常见于可选搜索参数场景。不能靠= ISNULL(@p, col)这类写法——它可能让索引失效,且语义模糊。
- 安全模式:
WHERE (@name IS NULL OR name = @name) AND (@age IS NULL OR age = @age) - 注意顺序:带
DEFAULT NULL的存储过程参数必须放在参数列表末尾,否则调用时跳过中间参数会报错expects parameter '@p2', which was not supplied - 别用
WHERE col = (SELECT val FROM t WHERE id = 1)这种标量子查询做条件,子查询返回NULL时整行被过滤;改用EXISTS或显式加IS NOT NULL
计算或拼接时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可能导致字段留空甚至整行插入失败
最易被忽略的一点:SELECT … INTO @var 在查不到数据时,@var不会变成NULL,而是保持上一次的值。后续逻辑若默认“没查到 = 空”,就会出错。必须显式初始化:SET @var = NULL,或改用COALESCE((SELECT col FROM t WHERE id = 123), 'default')。











