生产环境严禁使用select *,因其强制读取所有字段,导致磁盘i/o增加、网络传输膨胀、内存压力翻倍,并绕过覆盖索引引发回表或全表扫描,同时破坏代码稳定性、带来安全风险;正确做法是显式指定所需字段,如select first_name, email, created_at from users。

SELECT 后面不写 *,先列具体字段名
直接用 SELECT * 看起来省事,但实际会拖慢查询、暴露无关字段、让后续代码更难维护。生产环境里,数据库要读取所有列的磁盘页、网络要传更多字节、应用层还得解析不需要的字段——这些开销加起来可能翻倍。
正确做法是明确写出需要的列:
-
SELECT first_name, email, created_at FROM users;—— 只取三个字段,哪怕表有 20 列 - 如果字段名含空格或关键字(如
order),用反引号包裹:SELECT `order`, `user name` FROM orders; - 别名用
AS显式声明:SELECT email AS user_email FROM users;,避免歧义
FROM 必须跟真实存在的表名,大小写敏感要看数据库
MySQL 默认对表名大小写不敏感(Linux 下例外),PostgreSQL 和 SQL Server 则严格区分大小写。执行 SELECT * FROM Users; 在 PostgreSQL 里很可能报错 relation "Users" does not exist,而 SELECT * FROM users; 才对。
建议统一用小写表名,并确认当前数据库的命名规则:
- 查当前库有哪些表:
SHOW TABLES;(MySQL)或\dt(psql) - 不确定时,先用
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';(PostgreSQL)或对应系统视图 - 表名别拼错,比如
user_info写成user_infos或userinfo都会直接失败
WHERE 条件写在 FROM 之后,别漏掉 AND/OR 的括号优先级
多个条件混用时,AND 和 OR 的执行顺序容易出错。例如 WHERE status = 'active' OR role = 'admin' AND dept = 'tech' 实际等价于 WHERE status = 'active' OR (role = 'admin' AND dept = 'tech'),不是你想查“活跃用户”或“技术部管理员”的本意。
稳妥写法是主动加括号:
WHERE (status = 'active') OR (role = 'admin' AND dept = 'tech')- 字符串值必须用单引号:
WHERE name = 'Alice',双引号在某些数据库(如 PostgreSQL)会被当成标识符 - 数值不用引号:
WHERE age > 25,写成WHERE age > '25'可能触发隐式转换,索引失效
ORDER BY 和 LIMIT 要放最后,且 LIMIT 不能单独用
ORDER BY 必须出现在 WHERE 之后、LIMIT 之前;LIMIT 不能脱离 ORDER BY 单独用于分页——否则结果顺序不可靠,两次查同一页可能拿到不同数据。
典型安全写法:
SELECT id, title FROM articles WHERE published = true ORDER BY created_at DESC LIMIT 10;- 分页第二页:
... ORDER BY created_at DESC LIMIT 10 OFFSET 10; - SQLite 用
LIMIT 10 OFFSET 10,MySQL 8.0+ 支持,旧版 MySQL 用LIMIT 10,10,PostgreSQL 只认OFFSET/LIMIT顺序
最容易被忽略的是:没有 ORDER BY 的 LIMIT 查询,数据库返回哪几行完全取决于存储顺序和执行计划,下次执行可能完全不同——这不是 bug,是规范行为。










