为什么在MySQL DML语句中不建议使用SELECT * 而要列出字段?

梦静大大_9778

梦静大大_9778

2026-08-18

250人浏览

原创

在 mysql 的 dml 语句中使用 select * 不仅破坏可维护性,更会引发字段错位、类型不匹配、权限越界甚至语法错误——它不是“能跑就行”,而是“一动就崩”。

为什么在mysql dml语句中不建议使用select * 而要列出字段?

直接说结论:在 MySQL 的 DML 语句(如 INSERT ... SELECT、REPLACE ... SELECT、UPDATE ... JOIN 子查询等)中使用 SELECT * 不仅破坏可维护性,更会引发字段错位、类型不匹配、权限越界甚至语法错误——它不是“能跑就行”,而是“一动就崩”。

INSERT INTO t1 SELECT * FROM t2 容易字段错位

当目标表 t1 和源表 t2 字段顺序或数量不一致时,SELECT * 会按物理列序硬绑定,而非按名称映射。

  • 如果 t2 执行过 ALTER TABLE t2 ADD COLUMN created_at TIMESTAMP FIRST,SELECT * 返回的第一列变成 created_at,但 t1 第一列仍是 id → 插入值错位,id 被写入时间戳,整行数据损坏
  • t1(id INT, name VARCHAR(50)) 和 t2(name VARCHAR(50), id INT) 表结构相同但顺序不同,INSERT INTO t1 SELECT * FROM t2 会把 t2.name 写进 t1.id,触发 Incorrect integer value 或静默截断
  • MySQL 9.6.0 起对 container_aware 场景更敏感,字段错位可能被审计日志捕获为数据一致性事件,但不会回滚

UPDATE ... (SELECT * FROM subquery) 触发列名冲突或解析失败

子查询里用 SELECT *,尤其涉及 JOIN 多表时,MySQL 无法消歧义,直接报错。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • UPDATE users u SET status = (SELECT * FROM logs l WHERE l.user_id = u.id LIMIT 1) → 报错 Subquery returns more than 1 column,因为 logs 有 id、user_id、action、created_at 等多列
  • 即使单表,SELECT * 在子查询中也禁止用于标量子查询(必须返回单值),而开发者常误以为“只有一行就安全”
  • ShardingSphere 或 MyCat 等中间件解析该 SQL 时,因无法推断列名与类型,会拒绝路由或返回空结果,且无明确错误码

权限校验失效:DBA 开的最小权限形同虚设

DBA 给应用账号只授予了 SELECT(id, name, email) 权限,但 SELECT * 会绕过列级权限控制,读出未授权字段。

  • MySQL 8.0+ 支持列级权限,但 SELECT * 在权限检查阶段被当作“请求所有可见列”,只要用户对表有 SELECT 权限,就无视列白名单
  • 若表含 password_hash、ssn 等敏感字段,INSERT INTO audit_log SELECT * FROM users 会把它们全 dump 出来,违反 GDPR/等保要求
  • 审计日志中该操作标记为 access_type: FULL_TABLE_SCAN,但不会告警“越权读取”,需额外配置列访问监控规则

EXPLAIN 显示 Using temporary + Using filesort 就是 * 在拖后腿

哪怕只是 INSERT INTO tmp SELECT * FROM t WHERE x = ?,优化器也无法预估输出宽度,被迫启用临时表和磁盘排序。

  • SELECT * 让优化器放弃估算行大小,转而按最大可能宽度(如 TEXT/BLOB 占位)分配内存 → 触发 Using temporary
  • 如果 t 有 KEY idx_x (x),但 SELECT id,x FROM t WHERE x = ? 可走覆盖索引;换成 SELECT * 后,EXPLAIN 中 Extra 变成 Using where; Using temporary; Using filesort
  • 云环境 buffer pool 命中率低于 75% 时,这种临时表操作会显著拉高 Innodb_buffer_pool_reads 和 Created_tmp_disk_tables

最常被忽略的是:DML 场景下 SELECT * 的风险比纯查询更高——它不只读,还写、还改、还传播。一次 ALTER TABLE 加字段,可能让运行半年的定时同步任务突然写坏千万条记录,而日志里只有一行 ERROR 1366 或静默丢弃。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4003

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

851

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1049

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5881

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2783

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5860

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7781

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1050

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

932

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 180人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 287人学习