where中需显式处理null和空字符串:用is not null and trim(col) != '';日期字段先正则校验格式再转换;避免隐式类型转换和函数导致索引失效;正则语法因数据库而异,需适配。

WHERE子句中如何识别并排除NULL和空字符串
很多看似“干净”的字段其实混着NULL或'',直接用= 'xxx'会漏掉NULL行(因为NULL = 'xxx'结果为UNKNOWN),也容易把空字符串当成有效值。必须显式处理这两类。
- 用
IS NOT NULL判断非空,不能写!= NULL或NULL——这些永远不成立 - 对字符串字段,建议组合使用:
WHERE col IS NOT NULL AND TRIM(col) != '',TRIM()能干掉首尾空格导致的假“非空” - 某些数据库(如PostgreSQL)支持
NULLS FIRST/LAST,但WHERE里不生效,别混淆
用正则或模式匹配过滤格式非法的数据
邮箱、手机号、日期字符串这类字段,光看非空不够,还得验格式。不同数据库的正则函数名和语法差异大,容易写错。
- MySQL 8.0+ 用
REGEXP_LIKE(col, '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$');5.7及以前只能用REGEXP操作符,且不支持?等扩展语法 - PostgreSQL 用
col ~ '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$',注意大小写敏感,要忽略大小写加~* - SQL Server 没原生正则,得用
LIKE配合通配符(如email NOT LIKE '%[^a-zA-Z0-9._%+-@]%' AND email LIKE '%@%.%'),但覆盖不全,强烈建议升级到2017+后用STRING_SPLIT+ CLR或外部清洗
时间字段越界和类型转换失败的防御写法
从日志或ETL导入的数据常含'9999-99-99'、'0000-00-00'或'2024/13/01'这类无效日期,直接CAST(col AS DATE)在多数数据库会报错中断查询。
- PostgreSQL 可用
TO_DATE(col, 'YYYY-MM-DD') IS NOT NULL兜底,但需确保格式一致;更稳的是先col ~ '^\d{4}-\d{2}-\d{2}$'再转 - MySQL 用
STR_TO_DATE(col, '%Y-%m-%d') IS NOT NULL,注意它对非法值返回NULL而非报错,可安全用于WHERE - 避免在
WHERE里直接CAST()或CONVERT(),尤其SQL Server——类型转换失败会直接抛Conversion failed错误
WHERE条件顺序影响性能,但不影响逻辑结果
很多人以为把“快”的条件放前面能加速,实际上SQL优化器会重排执行顺序。真正影响性能的是索引是否命中、以及条件能否走索引。
-
WHERE status = 'active' AND LENGTH(name) > 0:前者若在status上有索引,大概率走索引;后者LENGTH()是函数,会导致该列索引失效 - 想让
name也走索引?建函数索引(PostgreSQL/Oracle支持CREATE INDEX idx_name_len ON t ((LENGTH(name)))),MySQL 8.0+ 支持函数索引,5.7不支持 - 多个
OR条件(如type = 'A' OR type = 'B')尽量改写成IN,更易被优化器识别为范围扫描
最常被忽略的是隐式类型转换——比如WHERE user_id = '123',当user_id是整型时,数据库可能放弃索引做全表扫描。查慢查询时,第一眼先盯EXPLAIN输出里的type和key列,而不是调换WHERE顺序。










