SELECT *代表选择表中的所有列,而非全部数据;它返回当前查询上下文(含权限、隔离级别、过滤条件等)下可见的所有列值,但不保证包含被WHERE过滤、RLS限制或事务隐藏的行。

SELECT * 会查出所有列,但不等于“全部数据”
直接写 SELECT * 确实能返回表中所有列的值,但它不会自动包含被 WHERE 过滤掉的行、被 GROUP BY 合并掉的重复行,也不会返回被事务隔离级别隐藏的未提交变更。真正“全部数据”取决于你当前的查询上下文和权限。
常见错误现象:SELECT * 在视图或有行级安全策略(RLS)的表上可能只返回部分行;在 PostgreSQL 中若用户没有某列的 SELECT 权限,* 会报错而非跳过该列。
- 如果只要物理存储的所有行(忽略权限和事务),确保在
READ COMMITTED或更低隔离级别下执行,且用户拥有整表SELECT权限 - 避免在生产环境长期用
SELECT *:列顺序可能随ALTER TABLE改变,ORM 或下游解析容易出错 - 想查“全部”包括被软删除的记录?得确认是否要加
WHERE deleted_at IS NULL这类条件
MySQL 和 PostgreSQL 对“全部数据”的默认行为差异
MySQL 默认使用 REPEATABLE READ 隔离级别,同一事务内多次执行 SELECT * 返回相同快照;PostgreSQL 默认是 READ COMMITTED,每次执行都看到最新已提交数据。这意味着,在高并发写入场景下,两次 SELECT * 可能返回不同结果集——这不是 bug,是隔离级别的正常表现。
性能影响明显:对大表执行 SELECT * 会触发全表扫描 + 所有列 I/O,即使只用其中 1–2 列。PostgreSQL 的 seq scan 和 MySQL 的 Handler_read_rnd_next 计数器会飙升。
- MySQL 8.0+ 可用
EXPLAIN FORMAT=TREE查看是否走索引覆盖;若没覆盖,*一定触发回表 - PostgreSQL 中
SELECT *无法利用仅包含部分列的索引(如CREATE INDEX ON t(a,b)),除非重写为SELECT a,b - SQL Server 用户注意:
SELECT *在含TEXT/IMAGE列的旧表上可能因 LOB 溢出导致严重延迟
真正需要“全部数据”时,必须显式处理 NULL 和隐藏行
很多业务表用 is_deleted BOOLEAN DEFAULT FALSE 或 status VARCHAR 标记逻辑删除。此时 SELECT * 默认查不到这些行——它们不是被删了,而是被 WHERE 条件隐式过滤了。同理,分区表中不在当前分区键范围内的数据也不会出现。
另一个常被忽略的是:某些数据库(如 SQLite)允许插入 NULL 值到主键列(除非声明 NOT NULL),而 SELECT * 会照常返回这些行,但后续 JOIN 或应用层空值处理可能崩掉。
- 检查表结构:
DESCRIBE table_name(MySQL)或\d table_name(psql)确认是否有默认WHERE条件(如物化视图定义) - 确认是否需包含被
TRIGGER动态屏蔽的行(例如审计表中visible = true才展示) - 导出全量数据做备份?别只靠
SELECT *:用mysqldump或pg_dump才能保证约束、索引、权限一并导出
替代 SELECT * 的更可控写法
明确列出字段名不只是为了可读性,更是控制“什么是全部”的关键。比如 SELECT id, name, created_at 比 * 更稳定,也更容易加 COALESCE(status, 'unknown') 这类兜底逻辑。
当字段多且易变时,可用元数据生成列名列表:SELECT column_name FROM information_schema.columns WHERE table_name = 'users' ORDER BY ordinal_position(标准 SQL),再拼成查询语句——但注意这不能解决权限或 RLS 问题。
- 临时查全部字段调试?用 IDE 的自动补全或
SELECT * FROM t LIMIT 0快速看结构,别真跑全量 - 需要动态列?考虑 JSON 构造:
SELECT row_to_json(t.*) FROM users t(PostgreSQL),比*更易序列化 - 跨库迁移时,
SELECT col1,col2,...能提前暴露类型不兼容(如 MySQLTINYINTvs PostgreSQLBOOLEAN)
真实场景里,“全部数据”从来不是语法问题,而是权限、一致性、业务定义的混合体。哪怕只差一行没查出来,也可能是因为你没注意到那个默默生效的行级策略,或者事务还没提交。

















