用 is null 判断空值,= null 永不成立;排序加唯一字段保稳定;left join 筛右表条件须放 on;like '%xxx' 会导致全表扫描。

WHERE 条件里用 = 还是 IS NULL?
查不到数据,十有八九是 NULL 值没处理对。= NULL 永远返回 false,SQL 标准里 NULL 不参与任何等值比较。
实操建议:
- 判断字段是否为空,必须写
WHERE col IS NULL,不能写WHERE col = NULL - 想同时匹配空字符串和 NULL,得拆开写:
WHERE col IS NULL OR col = '' - 如果用到了
COALESCE(col, '') = 'xxx',注意它会把 NULL 转成空字符串再比,但可能掩盖真实数据分布 - 某些 ORM(比如 Django 的
filter(field__isnull=True))底层自动转成IS NULL,但手写原生 SQL 时绝不能偷懒
ORDER BY 后加 LIMIT 为什么有时结果不稳?
排序字段有重复值时,ORDER BY col LIMIT 10 可能每次返回不同行——数据库没义务保证相同排序值内部的顺序。
实操建议:
- 只要业务上需要稳定分页或取 Top N,就在
ORDER BY末尾补一个唯一字段,比如:ORDER BY created_at DESC, id DESC LIMIT 10 - 避免只按
status或type排序后直接LIMIT,这类字段基数低、重复多 - MySQL 8.0+ 和 PostgreSQL 支持窗口函数,用
ROW_NUMBER() OVER (ORDER BY ...)更可控,但别在大表上滥用
JOIN 多张表时,ON 和 WHERE 的位置影响结果吗?
影响很大,尤其涉及 LEFT JOIN 时。把过滤条件错放 WHERE 里,会把本该保留的左表 NULL 行干掉。
实操建议:
-
ON只决定“怎么连”,WHERE是“连完再筛”。想保留左表全部记录,筛选右表字段的条件必须写在ON里 - 错误写法:
LEFT JOIN orders ON users.id = orders.user_id WHERE orders.status = 'paid'→ 实际变成内连接 - 正确写法:
LEFT JOIN orders ON users.id = orders.user_id AND orders.status = 'paid' - 如果真要筛左表,比如只看活跃用户,那
WHERE users.is_active = 1才该放WHERE
LIKE '%keyword%' 为什么慢得像卡住?
前导通配符(% 开头)让索引完全失效,数据库只能全表扫描。
实操建议:
- 能用
=就别用LIKE;能用LIKE 'prefix%'就别用LIKE '%suffix' - 模糊搜索需求强的场景,考虑加全文索引(MySQL 的
FULLTEXT,PostgreSQL 的tsvector),或者引入 Elasticsearch - 临时救急:给字段加函数索引(如 PostgreSQL 的
CREATE INDEX idx_name_lower ON users ((lower(name)))),配合WHERE lower(name) LIKE lower('%xxx%') - 别在
LIKE里拼接用户输入却不做转义,_和%是通配符,要用ESCAPE或预处理
复杂点不在语法多难,而在每个操作背后都有执行路径和数据分布的隐含假设。写一条查询前,先想清楚:我是在找数据,还是在告诉数据库怎么找。










