select into outfile最快但常不可用,须先查secure_file_priv值:null则禁用,路径则限写入该目录,空字符串极少见;导出需指定fields terminated by、optionally enclosed by和lines terminated by,且文件名不能重复、路径末尾不能有斜杠。

SELECT ... INTO OUTFILE 是最快的方法,但90% 的实际场景下它根本不能用——不是语法不会写,而是权限、路径、云环境三重限制直接卡死。
确认 secure_file_priv 是否允许导出
这是所有操作的前提,跳过这步等于白忙。
执行:SHOW VARIABLES LIKE 'secure_file_priv';- 返回
NULL:导出功能被完全禁用,INTO OUTFILE会报错ERROR 1290,立刻放弃 - 返回具体路径(如
/var/lib/mysql-files/):只能往这个目录写,且 MySQL 进程必须有写权限(常见问题:文件写进去了,但你是普通用户,ls都看不到) - 返回空字符串:极少见,理论上任意路径都行,但 MySQL 默认不这么配,别猜,以
SHOW结果为准
注意:secure_file_priv 是启动参数,改完要重启 MySQL 才生效,线上环境基本没权限动。
INTO OUTFILE 的字段包裹和换行必须显式指定
MySQL 默认用制表符分隔、不加引号、不写表头——直接导出会崩 CSV 解析。
关键参数不能省:
-
FIELDS TERMINATED BY ',':强制用逗号,别依赖默认的\t -
OPTIONALLY ENCLOSED BY '"':只给字符串字段加双引号,避免含逗号、换行的字段破坏结构 -
LINES TERMINATED BY '\n':Linux/macOS 用\n,Windows 服务器建议用\r\n,否则 Excel 打开可能粘成一行
示例(必须用绝对路径):
SELECT id, name, created_at FROM users WHERE status = 'active' INTO OUTFILE '/var/lib/mysql-files/active_users.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
常见坑:
- 路径末尾不能有斜杠(
/var/lib/mysql-files/✅,/var/lib/mysql-files//❌) - 文件名不能已存在,否则报错
ERROR 1086 - 导出后文件属主是
mysql用户,你得sudo chown $USER /var/lib/mysql-files/active_users.csv才能scp下来
当 INTO OUTFILE 不可用时,用 mysql 命令行 + sed 替换
这是最通用的兜底方案,不依赖服务端权限,适合连接远程 RDS 或阿里云 MySQL。
核心命令:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
mysql -u root -p -h db.example.com mydb -e "SELECT id, name FROM users WHERE updated_at > '2026-01-01'" | sed 's/\t/,/g' > users.csv
但要注意:
-
mysql默认输出是制表符分隔,sed 's/\t/,/g'只解决分隔符,不处理字段内含逗号或换行的问题 - 如果数据里有真实逗号(比如地址字段),这一行 CSV 就会错位,Excel 打开直接乱掉
- 中文字段名或内容可能乱码,加
--default-character-set=utf8mb4参数强制编码 - 表头不会自动加,想带列名就加
-B参数(但会多出边框字符,得再sed清洗)
更稳的做法是用 awk 做基础转义(虽然仍不如真正 CSV 库严谨):
mysql --raw --batch -u root -p mydb -e "SELECT id, name FROM users" | awk 'BEGIN{FS="\t"; OFS=","} {for(i=1;i users.csv
表头怎么加?别用 UNION ALL 硬拼
很多人用:
SELECT 'id', 'name' UNION ALL SELECT id, name FROM users INTO OUTFILE ...
这看似简单,但会出问题:
- 字段类型不一致:
'id'是字符串,id是整数,MySQL 可能隐式转换导致数值变科学计数法(比如123456789012345→1.23457e+14) - NULL 值会被转成空字符串,和真实 NULL 混淆
-
UNION ALL要求所有 SELECT 列数、类型严格一致,稍不注意就报错
真正稳妥的方式只有两种:
- 用客户端工具(DBeaver/Navicat)勾选“导出含表头”,它们内部做了类型对齐
- 在命令行导出后,用
sed -i '1i\id,name'插入表头(前提是字段顺序和 SELECT 一致)
导出这件事,难点从来不在 SQL 语法,而在于路径权限、字符编码、字段转义这三个现实约束。你得先看 secure_file_priv,再决定走哪条路;别一上来就写 INTO OUTFILE,十次有九次卡在第一步。










