SQL中IF判断NULL不进分支,因三值逻辑下@var='active'遇NULL返回UNKNOWN,而IF仅响应TRUE;正确写法为IF @var IS NULL、IF @var='active' OR @var IS NULL或先用COALESCE清洗再比较。

IF 条件里判断 NULL 为什么总不进分支
因为 SQL 的三值逻辑中,@var = 'active' 遇到 @var 是 NULL 时返回 UNKNOWN,而 IF 只响应 TRUE,UNKNOWN 和 FALSE 都被跳过。这不是 bug,是设计如此。
错误写法:IF @status = 'active' BEGIN ... END → @status 为 NULL 时整个分支静默失效。
正确做法:
- 明确区分语义:用
IF @status IS NULL处理缺失场景 - 合并等值与空值逻辑:用
IF @status = 'active' OR @status IS NULL(按业务是否需包含空值) - 统一清洗后再判断:先
DECLARE @norm_status VARCHAR(20) = COALESCE(@status, 'unknown'),再IF @norm_status = 'active'
计算或拼接时遇到 NULL 导致结果全为 NULL 怎么办
NULL 参与算术、字符串连接、比较等操作,结果几乎总是 NULL。“未知 + 任何值 = 未知”,这不是意外,是设计如此。
数值计算必须兜底两个方向:COALESCE(price, 0) * COALESCE(qty, 0),只补一个会白搭。
字符串拼接要逐字段处理:COALESCE(first_name, '') + ' ' + COALESCE(last_name, ''),别指望 CONCAT() 自动容错(MySQL 中它遇 NULL 直接返 NULL)。
注意类型一致性:
- PostgreSQL 中
COALESCE(user_id, '0')会报错,必须显式转类型:COALESCE(user_id, 0::INTEGER) - SQL Server 推荐用
ISNULL(@val, 0)(性能略优),跨库迁移则优先COALESCE(@val, 0)
WHERE 中参数为 NULL 时如何跳过该条件
常见于可选搜索参数场景。核心是把“参数为空”和“字段匹配”拆成两个独立逻辑,用 OR 连接,避免整条条件被 UNKNOWN 拖垮。
安全模式:WHERE (@name IS NULL OR name = @name) AND (@age IS NULL OR age = @age)
容易踩的坑:
- 漏括号导致逻辑错乱:
@name IS NULL OR name = @name AND @age IS NULL实际等价于@name IS NULL OR (name = @name AND @age IS NULL) - 字符串还要防空格:
@keyword IS NULL OR DATALENGTH(@keyword) = 0 OR t.Title LIKE '%' + @keyword + '%' - 别用
name = ISNULL(@name, name)—— 表面简洁,但可能让索引失效
SELECT INTO 遇到空结果集,变量不会清空
这是最隐蔽的坑:SELECT col INTO @var FROM t WHERE id = 123; 如果没查到数据,@var 不会变成 NULL,而是保持上一次的值。后续逻辑如果依赖“查不到就等于空”,就会出错。
必须显式初始化变量:SET @var = NULL; 再执行 SELECT ... INTO。
更稳妥的做法是绕开 INTO:
- 改用标量子查询 +
COALESCE:SELECT COALESCE((SELECT col FROM t WHERE id = 123), 'default') - 检查是否查到数据:
IF @@ROWCOUNT = 0 THEN ...或IF NOT EXISTS (SELECT 1 FROM t WHERE id = 123)
别在触发器或循环里漏判 NULL,尤其在 BEFORE INSERT 中对 NEW.col 做运算前,必须确认它不是 NULL —— 否则像 UPPER(NEW.phone) 会静默失败或中断事务。

















