select语句需明确字段或*、别名统一用as、where禁用聚合函数、字符串用单引号;like前导通配不走索引;order by+limit分页建议游标法;子查询在from中须带别名;sql mode影响结果结构。

SELECT 语句怎么写才不会报错
MySQL 中最常出错的不是语法多难,而是漏掉关键部分或混淆执行顺序。比如 SELECT 后面跟了别名但没用 AS,或在 WHERE 里用了聚合函数——这些都会直接报错。
-
SELECT必须明确列出字段或用*,不能空着 - 字段别名建议统一用
AS(虽然省略也能运行,但易读性差且某些客户端会解析异常) -
WHERE子句不能出现COUNT()、SUM()这类聚合函数,要用HAVING - 字符串值必须用单引号
' ',数字不用,否则可能触发隐式转换导致索引失效
WHERE 和 LIKE 怎么配合做模糊查询
LIKE 是最常用的模糊匹配方式,但效率和写法很依赖字段类型与索引结构。如果对没有索引的文本字段做前导通配(如 LIKE '%abc'),几乎必然全表扫描。
- 前导通配符(
%在开头)无法使用 B-tree 索引,应尽量避免 -
LIKE 'abc%'可走索引,适合前缀匹配场景 - 区分大小写取决于字段的 collation,如
utf8mb4_0900_as_cs是区分的,utf8mb4_0900_ai_ci不区分 - 想查下划线
_或百分号%本身?得用ESCAPE:例如LIKE '100\%' ESCAPE '\'
ORDER BY 和 LIMIT 怎么组合才安全
ORDER BY 加 LIMIT 看似简单,但在分页场景中容易漏数据或重复——尤其当排序字段存在重复值时。
- 仅靠
LIMIT 10,20做分页,在高并发更新下可能跳过或重复记录 - 推荐用游标分页:基于上一页最后一条的
id或时间戳继续查,例如WHERE created_at > '2024-01-01' ORDER BY created_at LIMIT 20 -
ORDER BY字段必须出现在SELECT列表中(严格模式下),否则可能报错 - 若排序字段为 NULL,默认排在最前;可显式写
ORDER BY status DESC NULLS LAST(MySQL 8.0.22+ 支持)
子查询放在 WHERE 还是 FROM 里更合适
子查询位置直接影响执行逻辑和性能。放在 WHERE 中通常是标量子查询或 IN 列表,而放在 FROM 中本质是临时派生表,必须带别名。
-
WHERE id IN (SELECT user_id FROM logs):若子查询返回大量结果,可能被优化器转成EXISTS,但仍有性能风险 -
FROM (SELECT user_id, COUNT(*) c FROM logs GROUP BY user_id) t:必须加别名t,否则报错Every derived table must have its own alias - 相关子查询(引用外部表字段)性能通常较差,能改写成
JOIN就别硬套子查询 - MySQL 5.7 对子查询优化较弱,8.0 起引入物化机制,但复杂嵌套仍建议拆解验证执行计划
SELECT u.name, t.c AS login_count FROM users u JOIN ( SELECT user_id, COUNT(*) c FROM login_logs WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) GROUP BY user_id ) t ON u.id = t.user_id ORDER BY t.c DESC LIMIT 10;
真正容易被忽略的是:即使 SQL 语法完全正确,SELECT 的结果集结构也受 SQL mode 影响——比如开启 ONLY_FULL_GROUP_BY 后,GROUP BY 字段不全列在 SELECT 中就会报错。上线前务必确认目标环境的 mode 设置。











