mysql的select into outfile受secure_file_priv限制,仅允许导出到指定目录;需显式指定字段分隔符与行终止符,不自动处理引号转义;推荐用mysqldump或客户端工具导出csv。

SELECT INTO OUTFILE 权限不足导致报错 ERROR 1290 (HY000)
MySQL 默认禁止用 SELECT INTO OUTFILE 写入任意路径,这是安全限制。你执行时如果看到 ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option...,说明 mysqld 启动时加了 --secure-file-priv,只允许导出到指定目录(通常是 /var/lib/mysql-files/ 或空值表示禁用)。
- 查当前允许路径:
SHOW VARIABLES LIKE 'secure_file_priv';,返回值为空则彻底禁用该功能 - 不能改配置?那就别硬用
INTO OUTFILE,换mysqldump或客户端导出(见下一条) - 能改配置?需在
my.cnf中设secure_file_priv = /path/to/export/,并确保 MySQL 进程对该目录有写权限(不是仅 root 可写)
导出 CSV 的字段分隔与换行必须手动指定
SELECT INTO OUTFILE 不自动按 Excel 或 LibreOffice 的 CSV 规范处理引号、转义和换行符。它只是“原样拼接”,遇到字段含逗号、换行或双引号会直接破坏格式。
- 必须显式用
FIELDS TERMINATED BY ','和LINES TERMINATED BY '\n',否则默认是制表符分隔,Excel 打开会错列 - 含特殊字符的字段不会自动加双引号——MySQL 没这功能。想兼容 Excel,得靠应用层处理,或用
CONCAT+REPLACE手动包裹,但极难覆盖所有边界情况(比如字段里本身就有双引号+换行) - 示例安全导出(无引号,仅基础分隔):
SELECT id, name, created_at FROM users INTO OUTFILE '/var/lib/mysql-files/users.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
替代方案:用 mysqldump 导出更可靠
当数据量不大、不需要实时 SQL 查询结果、且你有 shell 权限时,mysqldump 是比 INTO OUTFILE 更稳的选择。它支持真正的 CSV 格式,并自动处理引号和转义。
- 命令示例:
mysqldump -u root -p --tab=/tmp --fields-terminated-by=',' --fields-optionally-enclosed-by='"' --lines-terminated-by='\n' mydb users
注意:--tab会生成两个文件(users.sql和users.txt),你要的是后者 - 不想要建表语句?加
--no-create-info - Windows 下换行符可能出问题,建议加
--lines-terminated-by='\r\n'再导出 - 权限要求低:只要 MySQL 账户有
SELECT权,不用FILE权限
客户端导出(如 MySQL CLI、DBeaver、TablePlus)更适合日常
开发或运维临时导几万行数据,根本不用碰服务端文件系统。本地客户端直连后“右键 → Export”或 \T + \t 命令更简单。
- MySQL CLI 中:
\T /tmp/out.csv开启日志,再执行SELECT ...;,最后\t关闭——但输出是纯文本,字段仍以 tab 分隔,需另存为 .csv 后用 Excel 重新导入(选分隔符) - DBeaver 默认导出就是标准 CSV,自动加引号、转义双引号、处理换行,勾选 “Quote all string values” 即可
- 注意:大表(>50 万行)用 GUI 工具可能卡死或 OOM,此时才考虑服务端导出
secure_file_priv 的实际值,以及误以为 MySQL 会像 Python 的 csv.writer 那样自动处理引号——它不会。











