最常漏掉的两种情况是只查NULL或只查空字符串,应同时用WHERE column IS NULL OR column = '';验证数据有效性需优先检查约束定义而非依赖SELECT扫描。

查 NULL 和空字符串最常漏掉的两种情况
SQL 里验证数据有效性,第一反应往往是 SELECT 查出来看看。但很多人只写 WHERE column = '' 或 WHERE column IS NULL,结果漏掉其中一种——特别是当字段允许 NULL 又默认填充空字符串时,IS NULL 和 = '' 是完全不重叠的两个集合。
实操建议:
- 总是同时检查:用
WHERE column IS NULL OR column = ''(注意:PostgreSQL 中空字符串和 NULL 不等价,MySQL 在严格模式下也区分) - 如果字段语义上“不允许为空”,但表结构没加
NOT NULL约束,这种SELECT就是唯一兜底手段 - 避免用
LENGTH(column) = 0替代= '',因为某些数据库对尾部空格做截断(如 MySQL 的CHAR类型),导致误判
用 CHECK 约束反查定义比 SELECT 更可靠
靠 SELECT 扫描全表验证,本质是亡羊补牢;真正有效的验证,得看约束是否已存在、是否被绕过。比如应用层插入时用了 INSERT IGNORE 或 ON CONFLICT DO NOTHING,约束可能被静默跳过。
实操建议:
- 查约束定义优先用系统表:MySQL 用
SELECT * FROM information_schema.CHECK_CONSTRAINTS;PostgreSQL 用SELECT conname, consrc FROM pg_constraint WHERE contype = 'c' - 注意约束是否启用:PostgreSQL 支持
NOT VALID约束(只约束新数据),查convalidated字段确认 - SQLite 的 CHECK 约束默认不强制(除非打开
PRAGMA ignore_check_constraints = OFF),光看建表语句会误判
WHERE 条件里用函数导致索引失效的典型陷阱
为了验证格式有效性,常写类似 WHERE LENGTH(phone) != 11 或 WHERE phone NOT LIKE '1[3-9]%' ,这类带函数或通配符前导的条件,会让索引直接失效,大表上 SELECT 变成全表扫描。
实操建议:
- 优先把校验逻辑下沉到约束或触发器,而不是依赖查询时计算
- 必须用函数校验时,考虑生成列(如 MySQL 5.7+ 的
GENERATED COLUMN)并对其建索引 -
LIKE '1%'能走索引,但LIKE '%1'不能;正则匹配(REGEXP)在多数引擎中一律无法使用索引
用 INFORMATION_SCHEMA 查约束比 SHOW CREATE TABLE 更稳定
有人习惯用 SHOW CREATE TABLE users 看约束,但输出格式不标准,不同版本 MySQL 返回字段名可能变化(比如 Create Table 字段名在 8.0 有调整),脚本解析容易崩。
实操建议:
- 跨版本兼容性要求高时,统一走
INFORMATION_SCHEMA:查约束用CHECK_CONSTRAINTS,查外键用KEY_COLUMN_USAGE,查非空用COLUMNS.IS_NULLABLE - PostgreSQL 没有
INFORMATION_SCHEMA的完整 CHECK 支持,得切回pg_constraint,别硬套 MySQL 写法 - 注意权限:某些数据库限制普通用户访问
INFORMATION_SCHEMA,报错可能是Access denied for user而不是语法问题
约束定义和实际数据之间永远存在时间差——应用可能还没部署新约束,或者旧数据根本没清洗。所以任何 SELECT 验证都得先确认:你查的是“当前规则下应合法的数据”,还是“历史上曾被接受但现已过时的数据”。这个边界不厘清,结果就只是看起来对。

















