select * from table_name 查询表中所有列的当前满足条件的行,并非绝对“全部数据”,受权限、事务、null渲染、大字段限制等上下文影响。

SELECT * FROM table_name 会查出所有字段,但不等于“全部数据”
很多人以为 SELECT * FROM users 就是查出表里“全部数据”,其实它只返回当前满足条件的行(默认无 WHERE 就是全表),且字段是表定义时的全部列——但如果有计算列、隐藏列(如 PostgreSQL 的 ctid)、或系统生成的元数据(如 SQL Server 的 %%physloc%%),这些不会被 * 包含。另外,视图或临时表中若存在列别名或表达式,* 展开后仍是原始表达式结果,不是“物理存储的全部”。
WHERE 条件遗漏导致看似“没查全”,其实是逻辑过滤生效了
常见现象:执行 SELECT * FROM orders 返回 0 行,但确认表里有数据。大概率是当前会话开启了事务且未提交,或该表受行级安全策略(RLS)、视图权限、或数据库级别的数据屏蔽规则限制。例如 PostgreSQL 启用 RLS 后,即使 SELECT * 也会被策略自动注入 WHERE 条件;SQL Server 开启了行级安全性后,用户只能看到自己所属部门的数据。
- 先运行
SELECT COUNT(*) FROM table_name确认物理行数 - 检查是否在事务中:
SELECT pg_backend_pid()(PostgreSQL)或DBCC USEROPTIONS(SQL Server)看isolation level - 确认当前用户是否有
SELECT权限,以及是否被策略/视图封装
NULL 值和空字符串容易被当成“没数据”,但它们是合法的查询结果
SELECT * FROM product 返回某行的 description 字段显示为空,不代表字段是空字符串或丢失,很可能是 NULL。不同客户端对 NULL 的渲染不同:DBeaver 显示为 <null></null>,MySQL CLI 显示为空白,某些 ORM 则转成空字符串或零值。这会导致误判“查出来是空的”。
- 显式检查:
SELECT id, description, description IS NULL AS is_null FROM product LIMIT 5 - 避免模糊判断:不要用
description = ''过滤 NULL,要用description IS NULL或COALESCE(description, '') = '' - 导出或对接 API 时,注意 NULL 在 JSON 中是
null,不是""或0
大数据量下 SELECT * 可能失败或超时,这不是语法问题而是执行策略问题
当表有千万级以上行或包含大字段(如 TEXT、JSONB、BLOB),SELECT * 容易触发内存溢出、网络超时、或被数据库主动中止(如 MySQL 的 max_allowed_packet、PostgreSQL 的 work_mem 限制)。这时错误信息通常是 Packet too large 或 out of memory,而不是语法报错。
- 优先加
LIMIT调试:SELECT * FROM logs LIMIT 10 - 生产环境避免
SELECT *,明确列出所需字段,尤其跳过大字段 - 如真需全量导出,改用命令行工具:
pg_dump -t table_name --inserts db_name(PostgreSQL)或mysqldump db_name table_name(MySQL)
实际查“全部数据”这件事,比看上去更依赖上下文:权限模型、事务状态、NULL 处理逻辑、客户端渲染方式、以及底层存储引擎对大对象的处理策略——这些细节往往比语法本身更容易让人卡住。











