最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为什么在SQL视图定义中不建议使用SELECT 星号 而应明确指定列名
时间:2026-06-23 08:58:46 编辑:袖梨 来源:一聚教程网
SQL视图中禁用SELECT *,因其导致列结构不可控、跨平台不一致、列名冲突、解析失败、性能下降及工具链失效。
在 SQL 视图定义中写 SELECT * 不是语法错误,但等于主动放弃对输出结构的控制权——视图一旦创建,列名、列序、列数就该是确定的,而 * 让它变成运行时才决定的黑盒。
视图列结构会被底层表变更悄悄破坏
视图定义本身不存储字段元数据,只存 SQL 文本。当你用 SELECT * 创建视图后:
- 后续对源表执行
ALTER TABLE ADD COLUMN updated_at DATETIME,视图查询结果会立刻多出一列,但视图定义里根本没这行代码 - 如果下游应用按位置取值(如
rs.getString(2)),或者 BI 工具靠列名自动映射字段,就会拿到错的数据甚至直接报错 - SQL Server 和 Access 对
*的解析逻辑不同,跨平台迁移时容易出现列序不一致
JOIN 多表时 SELECT * 必然触发列名冲突
两个表都有 id 字段?name 字段?created_at 字段?SELECT * 会让数据库当场报错:Column 'id' is ambiguous。
你必须显式限定:
- 用表别名前缀,比如
users.id AS user_id、orders.id AS order_id - 含空格或特殊字符的字段名(如
[E-mail Address])必须加方括号,否则解析失败 - 同语义字段需统一别名,例如
users.full_name AS name和admins.display_name AS name,避免下游硬编码依赖原始名
性能与执行计划会被 * 拖垮
SELECT * 不仅读得多,还让优化器“猜不透”你真正要什么:
- 本可走覆盖索引的查询(如
WHERE status = 1上有索引),改成SELECT *后,优化器发现索引里没有全部字段,被迫回表——EXPLAIN里Extra列从Using index变成Using where; Using index; Using temporary - 字段含
TEXT或BLOB时,单行物理大小暴涨,SELECT *会把整页数据全读进 buffer pool,哪怕你只关心id和title - MySQL 的
max_allowed_packet默认 4MB,大字段 +*容易触发Packets larger than max_allowed_packet are not allowed
工具链和 ORM 映射会因 * 失效
MyBatis 的 resultMap、JPA 的 @Column、Power BI 的自动列推断,全都依赖稳定且可预测的列名与顺序。
一旦源表新增字段,SELECT * 视图返回的列序可能变化(尤其在 MySQL 中 ALTER TABLE … FIRST / AFTER 改过字段位置),导致:
- MyBatis 把新字段值错映射到老字段属性上
- Power BI 刷新报表时提示 “column not found” 或列类型错乱
- Java 应用用
ResultSet.getObject(i)按索引取值,拿到完全无关的数据
最麻烦的是:这类问题往往不报错,只静默错位——查数据时看着都对,上线跑几天才发现统计口径全歪了。
相关文章
- 明末渊虚之羽防具有哪些排名 07-02
- 如何获取和平精英皮肤照片 07-02
- 空洞骑士丝之歌如何获取制造金属 07-02
- 鱼骨头螃蟹阵容如何搭配 07-02
- 战魂旅人玩法是什么 07-02
- 无限暖暖祝你幸福发饰如何获取 07-02