2010-04-20 77 views
131

我有一个文件,可以包含3到4列数值,用逗号分隔。空字段与例外规定,当他们在该行的末尾:MySQL从CSV数据加载NULL值

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

下表在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"; 

所得表:

 
+------+------+-------+------+------+ 
| 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.

编辑

显示的警告输出:

 
+---------+------+--------------------------------------------------------+ 
| 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    | 
+---------+------+--------------------------------------------------------+ 

回答

139

这将做你想做的。它读取第四场到一个局部变量,然后将实际字段值设置为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,'') 
; 
+0

是否对性能有影响? – Blacksonic 2013-04-18 07:48:37

+0

理论上,我想 - 但它全部在内存中,只能保存少量数据每行,所以我想它会是无限小的;但是如果你认为这可能是一个问题,你应该测试它。 – 2013-04-19 03:00:32

+2

我真的很喜欢这个答案。用户在下载csv时可以看到空字符串(在'SELECT INTO OUTFILE'查询中使用'IFNULL(Col,'')')来查看excel,然后上传接受它们为null,而不必处理'\ N '在csv中。谢谢! – chrisan 2013-09-29 15:47:28

2

预处理您输入CSV用\ n来代替空白项。

尝试在正则表达式:S/,, /,\ n,/ G和S /,$ /,\ N/G

好运。

+1

此正则表达式部分的作品,它并没有解决顺序空白项,例如,,,,会,\ n ,, \ -N, 应该是,如果你运行它两次, – ievgen 2016-06-22 19:12:58

+0

将总结答案可用和以前的评论。以下为我工作的顺序: sed -i's/,, /,\ N/g'$ file, sed -i's/,, /,/ g'$ file, sed -i' s/\ N,$/\ N/g'$文件, – 2016-12-03 23:43:53

95

MySQL manual说:

当阅读与LOAD DATA INFILE ,空数据或丢失列 用 '' 更新。如果您希望列中有NULL 值,则应在数据文件中使用\ N 。文字 “NULL”也可能在某些 的情况下使用。

所以,你需要替换\ n空白像这样:

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

感谢您的提示 - 我怀疑编辑原始源数据,但如果这是唯一的解决方法,我会尝试一下。 – Spiros 2010-04-20 13:55:01

+7

我了解你的怀疑态度,没有人喜欢编辑原始数据,但感觉不对。但是,如果您仔细考虑一下,就必须有一种方法来区分NULL和空字符串。如果空白条目被转换为NULL,则需要一个空字符串的特殊序列。这很好,有办法如何告诉MySQL如何处理空白条目虽然,像LOAD DATA INFILE'/tmp/testdata.txt'INTO TABLE moo TREAT BLANKS AS NULL ... – Janci 2010-04-20 14:17:46

+2

好的,但如果你有'领域“''是''name'的\”\ N“,\ N,”stuff“' – Jonathon 2013-08-25 01:42:18

5

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

mysql> show variables like 'sql_mode'; 
+0

谢谢!我正在摸索着试图解决为什么导入一个CSV列,我昨天成功导入到生产服务器上的空列并不适用于我全新的本地安装 - 这是我的案例的答案! – 2016-06-13 15:54:42