MySQL 从 CSV 数据加载 NULL 值

Posted

技术标签:

【中文标题】MySQL 从 CSV 数据加载 NULL 值【英文标题】:MySQL load NULL values from CSV data 【发布时间】:2011-02-10 03:29:15 【问题描述】:

我有一个文件,其中可以包含 3 到 4 列用逗号分隔的数值。空字段在行尾时除外:

1,2,3,4,5
1,2,3,,5
1,2,3

mysql 中创建了下表:

+-------+--------+------+------+---------+--------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +-------+--------+------+------+---------+--------+ |一个 |整数(1) |是 | |空 | | |二 |整数(1) |是 | |空 | | |三 |整数(1) |是 | |空 | | |四 |整数(1) |是 | |空 | | |五 |整数(1) |是 | |空 | | +-------+--------+------+------+---------+--------+

我正在尝试使用 MySQL LOAD 命令加载数据:

LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo FIELDS 
TERMINATED BY "," LINES TERMINATED BY "\n";

结果表:

+------+------+--------+------+------+ |一个 |二 |三 |四 |五 | +------+------+--------+------+------+ | 1 | 2 | 3 | 4 | 5 | | 1 | 2 | 3 | 0 | 5 | | 1 | 2 | 3 |空 |空 | +------+------+--------+------+------+

问题在于,当原始数据中的字段为空且未定义时,MySQL 出于某种原因不使用列默认值(即 NULL)并使用零。当字段全部丢失时正确使用NULL。

不幸的是,在这个阶段我必须能够区分 NULL 和 0,因此我们将不胜感激。

谢谢 S.

编辑

显示警告的输出:

+---------+------+-------------------------------- ------------------------------------+ |水平 |代码 |留言 | +---------+------+-------------------------------- ------------------------------------+ |警告 |第1366章不正确的整数值:第 2 行的列 'four' 的 '' | |警告 |第1261章第 3 行不包含所有列的数据 | |警告 |第1261章第 3 行不包含所有列的数据 | +---------+------+-------------------------------- ------------------------------------+

【问题讨论】:

随着数据模式的改变,我会使用d6tstack,它会在运行LOAD DATA之前对齐所有列。请参阅 d6tstack SQL examples 有关数据架构更改的部分。 【参考方案1】:

预处理您的输入 CSV 以将空白条目替换为 \N。

尝试正则表达式:s/,,/,\n,/g 和 s/,$/,\N/g

祝你好运。

【讨论】:

这个正则表达式部分有效,它不能解决连续的空白条目,例如 ,,,, will be ,\n,,\n, 如果你运行两次应该可以使用 会总结答案和之前的评论。以下为我工作,按顺序: sed -i 's/,,/,\N/g' $file, sed -i 's/,,/,/g' $file, sed -i 's/\ N,$/\N/g' $文件, 我想这样做,但我不清楚你是如何运行这个正则表达式的。如果您使用 MySQL 对文件运行它,这将是最好的解决方案。但是你不说,我也不想花很多时间在谷歌上搜索如何做一些不可能的事情。【参考方案2】:

MySQL manual 说:

使用 LOAD DATA 读取数据时 INFILE,空或缺失的列是 用''更新。如果你想要一个 NULL 列中的值,您应该使用 \N 在数据文件中。字面意思 在某些情况下也可以使用“NULL” 情况。

所以你需要像这样用 \N 替换空格:

1,2,3,4,5
1,2,3,\N,5
1,2,3

【讨论】:

感谢您的提示 - 我对编辑原始源数据持怀疑态度,但如果这是解决它的唯一方法,我会尝试一下。 我理解你的怀疑,没有人喜欢编辑原始数据,只是感觉不对。但是,如果您考虑一下,必须有一种方法可以区分 NULL 和空字符串。如果将空白条目转换为 NULL,则需要一个特殊的空字符串序列。很高兴有一种方法告诉 MySQL 如何处理空白条目,例如 LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo TREAT BLANKS AS NULL... 好的,但是如果你有Fields enclosed by: ""\N""name",\N,"stuff" 我可以验证至少对于“phpMyAdmin 3.5.5”没有\N 的样式被接受为表示NULL。请改用NULL,如本例所示:"name","age",NULL,"other","stuff" 我们有 MySQL 5.5.46-0+deb8u1。我尝试了 NULL 和 \N,只有 \N 对我们有用。【参考方案3】:

这会做你想做的事。它将第四个字段读入局部变量,然后将实际字段值设置为 NULL,如果局部变量最终包含一个空字符串:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(one, two, three, @vfour, five)
SET four = NULLIF(@vfour,'')
;

如果它们都可能是空的,那么你会将它们全部读入变量并拥有多个 SET 语句,如下所示:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(@vone, @vtwo, @vthree, @vfour, @vfive)
SET
one = NULLIF(@vone,''),
two = NULLIF(@vtwo,''),
three = NULLIF(@vthree,''),
four = NULLIF(@vfour,'')
;

【讨论】:

理论上,我想 - 但它都在内存中,每行只保存少量数据,所以我认为它是无穷小的;但如果您认为这可能是一个问题,您应该对其进行测试。 我真的很喜欢这个答案。用户在为 excel 下载 csv(在 SELECT INTO OUTFILE 查询中使用 IFNULL(Col,''))时可以看到空字符串 '',但随后上传接受它们为空,而不必处理 csv 中的 \N。谢谢! 对于我使用的日期 'NULLIF(STR_TO_DATE(@date1, "%d/%m/%Y"), "0000-00-00")' 我有一个 csv 文件,其中包含零 0 应转换为 NULL(因为所讨论的数据不可能有零值)以及空字符串。如何确保零和空字符串都转换为NULL 如果零值和空字符串在不同的列中,则只需对空字符串执行上述操作,对零执行类似操作:nullif(@vone, 0)【参考方案4】:

行为因数据库配置而异。在严格模式下,这会抛出错误,否则会发出警告。 以下查询可用于识别数据库配置。

mysql> show variables like 'sql_mode';

【讨论】:

谢谢!我正在摸不着头脑,试图弄清楚为什么我昨天在生产服务器上成功导入的带有空列的 CSV 在我全新的本地安装上不起作用——这就是我的答案!【参考方案5】:

显示变量

Show variables like "`secure_file_priv`";

注意:将您的 csv 文件保存在上述命令给出的位置。

create table assessments (course_code varchar(5),batch_code varchar(7),id_assessment int, assessment_type varchar(10), date int , weight int);

注意:这里的 'date' 列在 csv 文件中有一些空白值。

LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/assessments.csv' 
INTO TABLE assessments
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '' 
LINES TERMINATED BY '\n' 
IGNORE 1 ROWS 
(course_code,batch_code,id_assessment,assessment_type,@date,weight)
SET date = IF(@date = '', NULL, @date);

【讨论】:

【参考方案6】:

(变量 1,@变量 2,..) SET variable2 = nullif(@variable2, '' or ' ') >> 你可以放任何条件

【讨论】:

这可能会更好作为***.com/a/5968530/10376320的评论【参考方案7】:

在 UNIX 终端中使用以下 sed 命令将输入​​文件转换为包含 \N 的空白列数据:

sed -i 's/,,/,\\N,/g' $file_name

然后使用LOAD DATA INFILE命令加载到mysql

【讨论】:

以上是关于MySQL 从 CSV 数据加载 NULL 值的主要内容,如果未能解决你的问题,请参考以下文章

从 CSV NULL 值导入的 PostgreSQL 是文本 - 需要 null

使用查询将数据从 EXCEL/CSV 加载到 MYSQL?

使用“加载文件数据”时将真假字符串转换为布尔值

每天从 CSV 文件更新 MySQL(存储过程中不允许加载数据)

MySQL Workbench 从 CSV 导入 NULL

在 Python 中将 CSV 数据加载到 MySQL