mysql菜鸟教程
19.3 导出和导入数据
在日常数据库管理中,我们不仅需要进行完整的数据库备份,还经常需要将部分数据导出为其他格式(如 CSV、文本文件),以便与外部系统交换数据、进行数据分析,或者批量导入数据到数据库表中。MySQL 提供了灵活的工具来实现这些需求,其中最常用的是 SELECT INTO OUTFILE 和 LOAD DATA INFILE 语句。
一、导出数据:SELECT INTO OUTFILE
SELECT INTO OUTFILE 语句将查询结果直接写入服务器上的一个文件。你可以自定义字段分隔符、行终止符、引用字符等,以生成 CSV 或其他格式的文本文件。
基本语法
SELECT 列1, 列2, ... INTO OUTFILE '文件路径' [FIELDS TERMINATED BY '分隔符' [OPTIONALLY] ENCLOSED BY '引号字符' ESCAPED BY '转义字符'] [LINES TERMINATED BY '行终止符'] FROM 表名 [WHERE 条件];
常用选项说明
示例 1:导出 students 表为 CSV 文件
假设我们要将 students 表的所有数据导出为 CSV 格式,字段用逗号分隔,字符串字段用双引号包围,每行以换行符结束。
SELECT id, student_no, name, IFNULL(age, '') AS age, IFNULL(major, '') AS major INTO OUTFILE '/tmp/students.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM students;
注意:
文件路径必须是 MySQL 服务器可写的目录,且受 secure_file_priv 系统变量限制(详见后文)。
如果表中有 NULL 值,默认导出为 \N,可以使用 IFNULL 将其转换为空字符串或其他默认值。
示例 2:仅导出部分字段并添加标题行
虽然 SELECT INTO OUTFILE 本身不支持直接添加标题行,但可以通过 UNION 或使用 mysql 命令导出 CSV 时添加。不过,可以先导出数据,再手动添加标题,或者采用其他方法。
一种技巧是先查询字段名作为一行,再导出数据,但需要两次查询和合并文件,较麻烦。实际应用中常用 mysql 命令行工具来导出带标题的 CSV。
二、导入数据:LOAD DATA INFILE
LOAD DATA INFILE 语句是 SELECT INTO OUTFILE 的逆操作,它从文本文件中读取数据,快速插入到数据库表中。它通常比逐条 INSERT 语句快得多。
基本语法
LOAD DATA INFILE '文件路径' INTO TABLE 表名 [FIELDS TERMINATED BY '分隔符' [OPTIONALLY] ENCLOSED BY '引号字符' ESCAPED BY '转义字符'] [LINES TERMINATED BY '行终止符'] [IGNORE 行数 LINES] -- 跳过文件开头的行,如标题行 [(列1, 列2, ...)] -- 指定文件中列的顺序,如果与表中顺序不一致 [SET 列名 = 表达式]; -- 对读取的值进行转换
示例 3:从 CSV 文件导入数据到 students 表
假设备份文件 /tmp/students.csv 是我们刚才导出的 CSV,且文件没有标题行。导入语句如下:
LOAD DATA INFILE '/tmp/students.csv' INTO TABLE students FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' (id, student_no, name, @age, major) SET age = NULLIF(@age, ''); -- 将空字符串转为 NULL
说明:
我们使用了用户变量 @age 来接收文件中的年龄字段,然后通过 SET 子句将空字符串转换为 NULL,以匹配表中的允许 NULL 列。
如果文件中字段顺序与表中完全一致,可以省略列名列表。
示例 4:导入包含标题行的文件
如果 CSV 文件第一行是列名(标题行),可以使用 IGNORE 1 LINES 跳过它。
LOAD DATA INFILE '/tmp/students_with_header.csv' INTO TABLE students FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES (id, student_no, name, age, major);
三、关于 secure_file_priv 的注意事项
出于安全考虑,MySQL 限制了 INTO OUTFILE 和 LOAD DATA INFILE 可以操作的目录。系统变量 secure_file_priv 决定了允许读写的目录:
如果 secure_file_priv 设置为一个目录路径,则只能在该目录下进行导入导出。
如果设置为 NULL,则禁止导入导出操作。
如果设置为空(''),则允许在任何目录(不推荐,有安全风险)。
查看当前设置:
SHOW VARIABLES LIKE 'secure_file_priv';
如果路径受限,请将文件放在指定目录下,或者修改配置文件(需要重启服务)。
四、使用 mysql 命令行导出 CSV(带标题的常用方法)
许多开发者更习惯用 mysql 命令行工具结合重定向来生成 CSV,这种方法可以轻松添加标题行。
mysql -u root -p -e "SELECT id, student_no, name, IFNULL(age, '') AS age, IFNULL(major, '') AS major FROM students" school_db | sed 's/\t/,/g' > /tmp/students.csv
但这种方法生成的字段分隔符是制表符,通过 sed 替换为逗号。更可靠的方式是直接使用 mysql 的 --batch 选项并结合 sed 处理标题。
另一个方法是使用 INTO OUTFILE 配合外部脚本添加标题。不过,对于日常导出,使用 mysql 命令行并手动处理更常见。
五、使用 mysqlimport 工具导入数据
mysqlimport 是 MySQL 提供的一个命令行工具,本质上是 LOAD DATA INFILE 的封装,用于从文本文件导入数据到表。
基本语法:
mysqlimport -u root -p [选项] 数据库名 文件1 [文件2 ...]
常用选项:
--fields-terminated-by=, 指定字段分隔符。
--fields-enclosed-by='"' 指定字段包围符。
--lines-terminated-by='\n' 指定行终止符。
--ignore-lines=1 跳过文件前 N 行(用于跳过标题)。
--local 表示文件位于客户端本地(而不是服务器),MySQL 8.0 中需要此选项。
示例:导入 students.csv 到 school_db 数据库的 students 表(文件有标题行):
mysqlimport -u root -p --local --fields-terminated-by=',' --fields-enclosed-by='"' --ignore-lines=1 school_db /tmp/students.csv
注意:文件名(不含扩展名)必须与表名相同,即 students.csv 会导入到 students 表。
六、实践练习
将学生表的数据导出为 CSV 文件,要求字段用 | 分隔,字符串不加引号,文件存放在 /tmp/students_pipe.txt。
使用 LOAD DATA INFILE 将刚导出的文件导入到一个新的表 students_backup 中(需提前创建相同结构的表)。
尝试用 mysqlimport 导入一个带标题行的 CSV 文件。
常见问题与解决方案
文件权限问题:确保 MySQL 服务器进程对目标目录有读写权限。导出时文件由 MySQL 服务器创建,因此目录必须对 MySQL 用户可写。
字符集乱码:在导出和导入时,可以指定字符集。在 INTO OUTFILE 中不支持直接指定字符集,但可以通过设置会话变量 CHARACTER_SET_RESULTS 或使用 mysql 命令行的 --default-character-set 参数。
NULL 值处理:默认导出为 \N,导入时也会识别 \N 为 NULL。如果使用其他占位符,需要在 LOAD DATA 中用 SET 子句转换。
大文件性能:对于超大文件,LOAD DATA INFILE 是最高效的导入方式。可以临时禁用索引和外键检查以加速导入:
ALTER TABLE 表名 DISABLE KEYS; SET FOREIGN_KEY_CHECKS = 0; -- 执行 LOAD DATA SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE 表名 ENABLE KEYS;
小结
导出数据:SELECT INTO OUTFILE 将查询结果写入服务器文件,可自定义格式。
导入数据:LOAD DATA INFILE 从文件读取并插入数据,速度快。
secure_file_priv 限制操作目录,需注意配置。
mysqlimport 是命令行工具,方便批量导入。
实际开发中,CSV 是最常用的交换格式,掌握导出导入技巧能显著提升数据处理的效率。
至此,你已经掌握了通过文件与外部系统交换数据的基本方法。

发表评论
所有评论