NULL与''在SQL中行为截然不同:WHERE col = NULL恒不成立,须用IS NULL;空字符串用= ''匹配;聚合函数对二者处理差异大,需用NULLIF或COALESCE统一处理。
直接写 WHERE col = '' 能命中空字符串,但 WHERE col = NULL 永远不返回任何行——因为 SQL 中任何与 NULL 的等值比较(=、!=、)结果都是 UNKNOWN,而 WHERE 只接受 TRUE。
查 NULL 必须用 IS NULL,查非空字符串且排除 NULL 得写成:col != '' AND col IS NOT NULL。
col = '':只匹配存储值为零长度字符串的行col IS NULL:只匹配该列未赋值或显式设为 NULL 的行col = NULL 或 col != NULL:语法合法,但逻辑恒为假,无实际筛选效果COUNT(col) 忽略 NULL,但会计入 '';SUM()、AVG()、MAX()、MIN() 全部跳过 
NULL,却把 '' 当作有效值参与计算——这在字符类型上通常报错(如 SUM('') 在 PostgreSQL 报 invalid input syntax for type numeric),但在 MySQL 的宽松模式下可能隐式转为 0,造成静默偏差。
COUNT(*) 统计所有行,COUNT(col) 只统计 col IS NOT NULL 的行COALESCE(col, 'N/A') 可统一兜底,但注意:若 col 是 '',不会触发替换NULLIF(col, '') 可把空字符串转为 NULL,再配合聚合更安全标准 SQL 规定 NULLS FIRST / NULLS LAST,但 MySQL 默认把 NULL 排最前,PostgreSQL 默认排最后;而 '' 始终按字典序参与排序,和普通字符串一样。这意味着 ORDER BY name 的结果在不同数据库里,NULL 行的位置可能上下翻转,但 '' 行总在 'a' 前、' ' 后(因 ASCII 值为 0)。
NULLS LAST,但旧版只能靠 ORDER BY IF(col IS NULL, 1, 0), col 模拟'' 和 ' '(空格)不是一回事:LENGTH(' ') 是 1,LENGTH('') 是 0NULL 位置,否则同一页数据可能重复或丢失定义列为 TEXT DEFAULT '' 时,显式插入 NULL 会存成 NULL(除非加 NOT NULL 约束);但若列定义为 TEXT DEFAULT NULL,又没指定值,才真正存 NULL。更大的陷阱是某些客户端或 ORM 在字段为空时自动发 '' 而非 NULL,导致业务上“未填写”被记为“填了空值”。
NOT NULL DEFAULT '' 明确语义,避免歧义STRICT_TRANS_TABLES 模式下,向 NOT NULL 列插入 '' 是允许的;但插入 NULL 会报错NULL,而空字段(,,)可能是 '',需预处理统一真正麻烦的不是记不住规则,而是同一个字段在应用层、ORM 层、DB 层、迁移脚本里可能被不同方式初始化或校验——NULL 和 '' 看似微小,一旦混用,查数、统计、导出全会偏移。