登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL LOAD DATA 导入带引号换行的 CSV 怎么设置

来源:17golang原创

时间:2026-09-07 14:46:31 335浏览 收藏

MySQL 用 LOAD DATA 导入 CSV 时,真正决定结果的不是“文件扩展名是不是 csv”,而是文件里的三种边界是否和 SQL 一致:字段之间用什么分隔、字段是否由引号包住、每条记录在哪里结束。带逗号的备注要靠 ENCLOSED BY 保住,字段内换行要和 LINES TERMINATED BY 区分,字段中的双引号则要遵守生成器的转义约定。

常见的双引号 CSV 可以从 FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '\\' 和正确的 LINES TERMINATED BY 开始;如果一条记录的备注跨了多行,只要换行位于包围引号内,就应当仍属于同一字段。
要点速览
  • MySQL 默认按制表符分字段、按换行分记录,不会默认识别双引号 CSV。
  • FIELDS 要放在 LINES 前面;Windows 导出的文件通常需要 \r\n
  • CSV 里的 "" 可表示一个字面双引号;反斜杠转义则要让 ESCAPED BY 与生成器保持一致。

先把 CSV 的三层边界对齐

先不要急着改表结构。打开文件的原始内容,确认一行记录使用的是 LF(\n)还是 CRLF(\r\n),字段分隔符是不是逗号,文本字段是否总是由双引号包围。文件首行如果真的是列名,再使用 IGNORE 1 LINES;没有表头却加上它,会悄悄丢掉第一条数据。

下面的示例假设文件内容是:第一行是表头,note 里既可能有逗号,也可能有被双引号包住的换行;文件来自 Windows 导出,所以记录结束符为 CRLF。

order_id,customer_name,note
1001,"华东仓库","第一行备注
第二行备注"
1002,"华南仓库","含有逗号,仍是一个字段"
MySQL LOAD DATA 将 CSV 文件、字段分隔符、双引号包围符和行结束符对应到目标表的三层边界关系图
图1:CSV 文件的字段与记录边界,需要分别对应 LOAD DATA 的字段和行参数。

对应关系可以记成:逗号属于字段边界,双引号属于字段包围规则,CRLF 属于记录边界。三者混在一个参数里处理,最容易出现“备注被拆成两列”或“下一行顶到上一条记录”的错觉。

FIELDS 如何处理引号、逗号和转义

对上面的文件,可以先用这一条语句。示例把数据读入临时表,便于先抽样核对;LOCAL 表示文件从客户端机器提供,和字段解析规则是两个不同问题。

LOAD DATA LOCAL INFILE '/data/import/orders.csv'
INTO TABLE import_orders
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
       ENCLOSED BY '"'
       ESCAPED BY '\\'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(order_id, customer_name, note);

FIELDS TERMINATED BY ',' 告诉 MySQL 逗号是字段分隔符,ENCLOSED BY '"' 让两端的双引号不进入字段值。输入解析时,OPTIONALLY 不会改变包围符的识别;它主要影响输出文件是否给字符串列加包围符,所以导入时不必把它当成“允许换行”的开关。

转义字符必须看 CSV 生成器的约定:

文件中的写法LOAD DATA 重点设置导入后的含义
"华东,仓库"TERMINATED BY ',' + ENCLOSED BY '"'逗号是字段内容
"他说 ""可以"""保留 ENCLOSED BY '"'成对双引号变成一个字面双引号
"他说 \"可以\""ESCAPED BY '\\'反斜杠后的字符按转义规则读取

不要为了“更像标准 CSV”盲目把 ESCAPED BY 改成双引号。文件若用成对双引号表达字面引号,MySQL 本身就能按包围符规则识别;只有当上游确实用某个字符做转义前缀时,才让该参数匹配上游。

MySQL CSV 字段内逗号、双引号包围符、成对双引号和 ESCAPED BY 的静态数据结构关系图
图2:字段内逗号和双引号是否属于数据,取决于包围符与转义约定的组合。

LINES TERMINATED BY 如何保留字段内换行

LINES TERMINATED BY 描述的是一条记录的结束符,不是字段内容禁止出现换行。只要多行文本仍处在双引号包围范围内,解析器就应把它们归入同一个 note 字段。关键是按真实文件选择行结束符:

  • Linux 或多数容器导出的 LF 文件:LINES TERMINATED BY '\n'
  • Windows 程序常见的 CRLF 文件:LINES TERMINATED BY '\r\n'

如果把 CRLF 文件写成 \n,字段末尾可能残留 \r;反过来把 LF 文件写成 \r\n,也可能让行尾无法按预期匹配。遇到错位时,先用十六进制查看文件末尾的字节,比反复改 SQL 更快。

另外,IGNORE 1 LINES 只按文件开头忽略一条记录,不会修复中间某一行的引号不闭合。若某行的双引号缺失,后续换行都可能被当成前一条字段内容的一部分,这时要先修复文件或重新导出。

导入前后的检查与回滚

正式表前先准备一个结构相同的临时表,在临时表里抽样检查四件事:总行数、含逗号的备注、跨行备注、双引号是否被还原为一个字符。可以用简单查询把最容易错的字段挑出来。

-- 只核对解析后的文本,不修改正式表
SELECT order_id, customer_name, note
FROM import_orders
WHERE note LIKE '%,%'
   OR note LIKE CONCAT('%', CHAR(10), '%')
   OR note LIKE '%"%'
LIMIT 20;

如果抽样结果把一条 CSV 记录拆成多条,优先回看三项:文件实际行尾、字段是否都用同一种包围符、上游对双引号采用成对写法还是反斜杠写法。确认无误后再导入正式表;临时表出现错列时直接清空或删除临时表,避免用错误数据覆盖正式数据。

MySQL 8.4 手册的 LOAD DATA 说明还特别提醒,FIELDSLINES 的格式必须和生成文件时一致。把这条规则写进导入脚本旁边的注释或 README,下一次换导出工具时就能及时发现格式变化。

常见问题

不写 FIELDS 和 LINES 时,MySQL 默认按什么解析?

默认字段分隔符是制表符,记录结束符是换行,也不默认使用包围符;普通逗号 CSV 不能直接依赖默认值。

OPTIONALLY ENCLOSED BY 能解决字段内换行吗?

不能。它不是换行开关,换行归 LINES TERMINATED BY 管;输入时是否剥离包围符也不因 OPTIONALLY 改变。

为什么只改 TERMINATED BY 还是会错列?

因为字段里有逗号时,必须同时告诉 MySQL 双引号是包围符;如果字段里还有双引号,还要继续匹配上游的成对引号或转义字符约定。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>