mysql查询需规避null判断错误、缺失limit导致全表排序等陷阱:where中null必须用is null而非=,order by后须加limit以防性能崩溃。

MySQL 的 SELECT 语句不是“用不用”的问题,而是“怎么写才不踩坑、不出错、不慢、不漏数据”的问题。绝大多数查询错误和性能问题,都出在基础语法理解偏差或忽略隐含行为上。
WHERE 条件里 NULL 不能用 = 判断
这是新手最常栽跟头的地方:写 WHERE status = NULL 永远查不到任何行,因为 SQL 中 NULL 参与的任何等值比较(=、!=、)结果都是 UNKNOWN,不满足 WHERE 的真值要求。
- 正确写法是
WHERE status IS NULL或WHERE status IS NOT NULL - 如果字段可能为
NULL,又想统一处理(比如当默认值),可用COALESCE(status, 'unknown')或IFNULL(status, 'unknown') - 注意:索引列上使用
IS NULL通常能走索引,但IS NOT NULL在某些旧版本 MySQL 中可能触发全表扫描
ORDER BY 后没加 LIMIT 时的隐式风险
开发阶段随手写 SELECT * FROM orders ORDER BY created_at DESC 看着没问题,上线后可能拖垮数据库——尤其当表有百万行且 created_at 没索引时,MySQL 得排序全部数据再返回全部结果。
PHP是一种功能强大的网络程序设计语言,而且易学易用,移植性和可扩展性也都非常优秀,本书将为读者详细介绍PHP编程。 全书分为预备篇、开始篇和加速篇三大部分,共9章。预备篇主要介绍一些学习PHP语言的预备知识以及PHP运行平台的架设;开始篇则较为详细地向读者介绍PKP语言的基本语法和常用函数,以及用PHP如何对MySQL数据库进行操作;加速篇则通过对典型实例的介绍来使读者全面掌握PHP。 本书
- 除非明确需要全部结果,否则必须加
LIMIT;分页场景优先用游标(WHERE created_at ),而非 <code>OFFSET -
ORDER BY字段必须和WHERE条件中高选择性字段组合建联合索引,否则排序会走 filesort - 字符串字段排序要注意字符集和校对规则(如
utf8mb4_0900_as_cs区分大小写),可能影响结果顺序
JOIN 时 ON 和 WHERE 的执行时机差异
左连接中,把过滤条件写在 ON 还是 WHERE 会导致结果完全不同。例如:SELECT * FROM users u LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid',和把 o.status = 'paid' 移到 WHERE 后,前者保留所有用户(没支付订单的 o.* 为 NULL),后者实际变成内连接(NULL 被 WHERE 过滤掉)。
-
ON是连接过程中决定“哪些右表行能匹配进来”,WHERE是连接完成后对整行结果的最终筛选 - 多表
LEFT JOIN时,后续JOIN的ON条件只能引用左侧已存在的表,不能跨跳引用更早的表(MySQL 5.7+ 支持部分放宽,但语义易混淆) - 用
EXPLAIN看type和Extra字段,确认是否用了索引、是否产生临时表或 filesort
GROUP BY 严格模式下非聚合字段报错
MySQL 5.7 默认开启 sql_mode=ONLY_FULL_GROUP_BY,此时 SELECT id, name, COUNT(*) FROM users GROUP BY city 会直接报错,因为 id 和 name 不在 GROUP BY 列中,也不在聚合函数里。
- 解决方式只有三种:补全
GROUP BY id, name, city;或只选city和聚合字段;或用ANY_VALUE(id)显式声明接受任意值(需确认业务逻辑允许) - 不要轻易关掉
ONLY_FULL_GROUP_BY,它暴露的是查询逻辑缺陷,而不是配置问题 -
GROUP BY字段如果有函数包装(如DATE(created_at)),记得给该表达式建函数索引(MySQL 8.0+)或冗余生成列 + 索引
真正难的从来不是写出能跑的 SELECT,而是写出在数据量增长、并发升高、字段值分布变化后依然稳定、可预期、可维护的查询。每个 WHERE 条件、每处 JOIN、每次 GROUP BY,背后都有执行计划和索引策略在起作用——别让语法正确掩盖了语义风险。









