MySQL从CSV数据加载NULL值

Spi*_*ros 160 mysql csv load-data-infile

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

1,2,3,4,5
1,2,3,,5
1,2,3
Run Code Online (Sandbox Code Playgroud)

下表是在MySQL中创建的:

+-------+--------+------+-----+---------+-------+
| Field | Type   | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| one   | int(1) | YES  |     | NULL    |       | 
| two   | int(1) | YES  |     | NULL    |       | 
| three | int(1) | YES  |     | NULL    |       | 
| four  | int(1) | YES  |     | NULL    |       | 
| five  | int(1) | YES  |     | NULL    |       | 
+-------+--------+------+-----+---------+-------+

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

LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo FIELDS 
TERMINATED BY "," LINES TERMINATED BY "\n";
Run Code Online (Sandbox Code Playgroud)

结果表:

+------+------+-------+------+------+
| one  | two  | three | four | five |
+------+------+-------+------+------+
|    1 |    2 |     3 |    4 |    5 | 
|    1 |    2 |     3 |    0 |    5 | 
|    1 |    2 |     3 | NULL | NULL | 
+------+------+-------+------+------+

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

不幸的是,我必须能够在这个阶段区分NULL和0,所以任何帮助都将受到赞赏.

谢谢S.

编辑

SHOW WARNINGS的输出:

+---------+------+--------------------------------------------------------+
| Level   | Code | Message                                                |
+---------+------+--------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: '' for column 'four' at row 2 | 
| Warning | 1261 | Row 3 doesn't contain data for all columns             | 
| Warning | 1261 | Row 3 doesn't contain data for all columns             | 
+---------+------+--------------------------------------------------------+

Dun*_*ock 180

这将做你想要的.它将第四个字段读入局部变量,然后将实际字段值设置为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,'')
;
Run Code Online (Sandbox Code Playgroud)

如果它们都可能是空的,那么你将它们全部读入变量并有多个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,'')
;
Run Code Online (Sandbox Code Playgroud)

  • 对于日期,我使用'NULLIF(STR_TO_DATE(@ date1,"%d /%m /%Y"),"0000-00-00")' (8认同)
  • 我真的很喜欢这个答案.当用户下载csv(在`SELECT INTO OUTFILE`查询中使用`IFNULL(Col,'')`为excel时,用户可以看到空字符串'''',但是上传接受它们为null vs必须处理`\ N `在csv.谢谢! (3认同)
  • 如何在不提及特定列的情况下执行此操作?只为所有人? (2认同)

Jan*_*nci 126

MySQL手册说:

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

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

1,2,3,4,5
1,2,3,\N,5
1,2,3
Run Code Online (Sandbox Code Playgroud)

  • 我理解你的怀疑态度,没有人喜欢编辑原始数据,只是感觉不对.但是,如果你考虑一下,必须有一种方法来区分NULL和空字符串.如果将空白条目转换为NULL,则需要一个特殊的空字符串序列.很高兴有一种方法告诉M​​ySQL如何处理空白条目,比如LOAD DATA INFILE'/tmp/testdata.txt'INTO TABLE moo TREAT BLANKS AS NULL ... (7认同)
  • 感谢您的提示 - 我对编辑原始源数据持怀疑态度,但如果这是解决问题的唯一方法,我会尝试一下. (3认同)
  • 我可以验证至少对于"phpMyAdmin 3.5.5",没有接受`\ N`的样式表示'NULL`.而是使用`NULL`,如下例所示:``name","age",NULL,"other","stuff"` (3认同)
  • 好的,但是如果你有`字段括在:"`是``名称'的`\ N",\ N,"stuff"` (2认同)
  • 我们有 MySQL 5.5.46-0+deb8u1。我尝试了 NULL 和 \N,只有 \N 对我们有用。 (2认同)

小智 6

根据数据库配置,行为会有所不同.在严格模式下,这会抛出错误,否则会发出警告.以下查询可用于标识数据库配置.

mysql> show variables like 'sql_mode';
Run Code Online (Sandbox Code Playgroud)


Sam*_*man 5

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

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

祝你好运。

  • 将总结答案和之前的评论。以下对我有用,按顺序: sed -i 's/,,/,\N/g' $file, sed -i 's/,,/,/g' $file, sed -i 's/\ N,$/\N/g' $文件, (2认同)