2010-04-20 82 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