NULL不能用=判断,因SQL标准规定NULL不等于任何值(包括自身),WHERE col = NULL恒返回空集;必须用IS NULL/IS NOT NULL。
IS NULL 判断为什么不能用 = NULL
因为 sql 标准规定 null 不等于任何值,包括它自己。写 where col = null 永远不返回行,实际结果是空集,不是“没查到”,而是逻辑上被当成 unknown 直接过滤掉了。
- 必须用
IS NULL或IS NOT NULL—— 这是唯一合规的 NULL 判断方式 - 某些方言(如 PostgreSQL)支持
IS DISTINCT FROM,能安全比较含 NULL 的两列,但 MySQL、SQL Server 不支持 - ORM 里如果手写条件,比如 Django 的
filter(col__isnull=True),底层生成的就是IS NULL,别硬套__exact=None
COALESCE 返回值类型怎么定
COALESCE 不是简单取第一个非 NULL 值,它会按参数顺序做隐式类型转换,并以「最宽泛的那个类型」为最终返回类型。这直接影响计算和索引使用。
- 例如
COALESCE(int_col, 'fallback'):MySQL 会把int_col转成字符串,整个表达式变成VARCHAR,哪怕你只想要数字 - 在 WHERE 中用
COALESCE(col, 0) > 10,可能让索引失效——因为对列做了函数包装,优化器无法下推 - 推荐写法是先明确类型:比如
COALESCE(col::INTEGER, 0)(PostgreSQL),或用CASE WHEN col IS NOT NULL THEN col ELSE 0 END避免隐式转换
NULL 测试中容易漏掉的边界场景
真实数据里 NULL 很少单独出现,常混着空字符串、零值、空白字符一起干扰判断,光靠 IS NULL 会漏判。
-
''(空字符串)、' '(纯空格)、0、0.0全都不是 NULL,但业务上常当作“无效值”处理 - 字符串字段建议组合判断:
col IS NULL OR TRIM(col) = '';数值字段注意col IS NULL OR col = 0是否真符合语义 - JSON 字段(如 MySQL 的
JSON类型)里NULL和 JSON 文本"null"是两回事,col->>'key'返回的是字符串"null",不是 SQL NULL,得用col->'key' IS NULL才对
COALESCE 在 INSERT/UPDATE 里的坑
用 COALESCE 做默认值填充很常见,但要注意它在语句执行时才求值,且不触发 DEFAULT 约束逻辑。
-
INSERT INTO t (x) VALUES (COALESCE(?, 42)):如果参数传了NULL,确实插 42;但如果表定义了x INT DEFAULT 42,直接INSERT INTO t () VALUES ()才走 DEFAULT,而VALUES (NULL)会插进 NULL,不会自动 fallback - 触发器或生成列里用
COALESCE要小心循环:比如生成列定义为GENERATED ALWAYS AS (COALESCE(other_col, 'N/A')),若other_col本身是生成列且依赖本列,就报错 - 批量 UPDATE 时,
SET col = COALESCE(new_val, col)看似“只更新非 NULL 值”,但其实等价于“不更新”,因为col = col不触发变更日志,某些 CDC 工具会跳过这种语句
NULL 处理真正的复杂点不在语法,而在你得同时盯住三件事:SQL 标准行为、具体数据库的隐式规则、还有业务上“什么算空”——这三者很少完全重合。










