MySQL从CSV数据加载NULL值


167

我有一个文件,该文件可以包含3到4列以逗号分隔的数值。当空字段位于行末时,将定义为空字段:

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

下表是在MySQL中创建的:

+ ------- + -------- + ------ + ----- + --------- + ------- +
| 领域 类型 空| 关键 默认值| 额外|
+ ------- + -------- + ------ + ----- + --------- + ------- +
| 一| int(1)| 是的 | NULL | |
| 二| int(1)| 是的 | NULL | |
| 三| int(1)| 是的 | NULL | |
| 四 int(1)| 是的 | NULL | |
| 五| int(1)| 是的 | NULL | |
+ ------- + -------- + ------ + ----- + --------- + ------- +

我正在尝试使用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 | NULL | NULL |
+ ------ + ------ + ------- + ------ + ------ +

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

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

谢谢S。

编辑

SHOW WARNINGS的输出:

+ --------- + ------ + -------------------------------- ------------------------ +
| 级别| 代码 留言|
+ --------- + ------ + -------------------------------- ------------------------ +
| 警告| 1366 | 错误的整数值:“”对于第2行的“四”列
| 警告| 1261 | 第3行未包含所有列的数据|
| 警告| 1261 | 第3行未包含所有列的数据|
+ --------- + ------ + -------------------------------- ------------------------ +

对于这样的数据模式更改,我将使用d6tstack在运行之前对齐所有列LOAD DATA。有关数据架构更改,请参见d6tstack SQL示例部分。
citynorman '18 -10-14

Answers:


193

这将做您想要的。它将第四个字段读入局部变量,然后如果该局部变量最终包含一个空字符串,则将实际字段值设置为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,'')
;

从理论上讲,我想-但它们全都在内存中,并且每行只保存少量数据,因此我想对它进行成像是无穷大的。但是如果您认为这可能是一个问题,则应该对其进行测试。
Duncan Lock

4
我真的很喜欢这个答案。用户''在下载excel 的csv(IFNULL(Col,'')SELECT INTO OUTFILE查询中使用)但随后上传时将其视为空字符串,而不必\N在csv 中进行处理。谢谢!
克里斯安

9
对于我使用的日期'NULLIF(STR_TO_DATE(@ date1,“%d /%m /%Y”),“ 0000-00-00”)'
JoaquínL. Robles

1
我有一个csv文件,其中包含0应转换为零的零NULL(因为所讨论的数据不可能为零)和空字符串。如何确保零和空字符串都转换为NULL
Paul Rougieux

如果零值和空字符串在不同的列中,则只需对空字符串执行上述操作,并对零进行类似的操作:nullif(@vone, 0)
Duncan Lock

136

MySQL手册说:

使用LOAD DATA INFILE读取数据时,空白或缺失的列将用''更新。如果要在列中使用NULL值,则应在数据文件中使用\ N。在某些情况下,也可以使用文字“ NULL”。

因此,您需要像这样用\ N替换空格:

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

3
感谢您的提示-我怀疑要编辑原始源数据,但是如果这是唯一的解决方法,我会尝试一下。
Spiros

7
我了解您的怀疑,没有人喜欢编辑原始数据,只是感觉不对。但是,如果想一分钟,就必须有一种方法来区分NULL和空字符串。如果将空白条目转换为NULL,则需要为空字符串设置特殊序列。最好有一种方法告诉M​​ySQL如何处理空白条目,例如LOAD DATA INFILE'/tmp/testdata.txt'INTO TABLE moo TREAT BLANKS AS NULL ...
Janci 2010年

2
OK,但如果你有Fields enclosed by: ""\N""name",\N,"stuff"
乔纳森·

3
我可以验证至少对于“ phpMyAdmin 3.5.5”而言,没有任何样式\N表示为NULL。而是使用NULL,如本例所示:"name","age",NULL,"other","stuff"
Jonathon

1
我们有MySQL 5.5.46-0 + deb8u1。我尝试了NULL和\ N,只有\ N为我们工作。
raphael75 '16

6

行为因数据库配置而异。在严格模式下,这将引发错误或警告。以下查询可用于标识数据库配置。

mysql> show variables like 'sql_mode';

谢谢!我正在摸索尝试解决为什么昨天导入在生产服务器上成功导入的带有空列的CSV无法在全新的本地安装上工作-这就是我的答案!
艾玛·伯罗斯

3

预处理输入的CSV,以用\ N替换空白条目。

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

祝好运。


1
此正则表达式部分有效,它不能解决连续的空白条目,例如,,,,,将是,\ n ,, \ n,如果您运行两次,则应该可用
ievgen

1
将总结答案和先前的评论。以下为我工作,顺序为:sed -i's / ,,,, \ N / g'$ file,sed -i's / ,, /,/ g'$ file,sed -i's / \ N,$ / \ N / g'$ file,
Omar Khazamov

我想这样做,但是我不清楚您如何运行此正则表达式。如果您正在使用MySQL对文件运行它,那么这将是最佳解决方案。但是您没有说,我也不想花费大量时间来搜索如何做一些不可能的事情。
DonkeyKong

1

(variable1,@ variable2,..)SET variable2 = nullif(@ variable2,''或'')>>您可以放置​​任何条件


0

显示变量

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.