2013-06-11 9 views
7

Ho un sacco di dati CSV che ho bisogno di caricare in un database MySQL. Bene, CSV-ish, forse. (modifica: actually, it looks like the stuff described in RFC 4180)CARICARE DATI dal file CSV in cui è stato utilizzato il carattere di escape come carattere di escape

Ogni riga è un elenco di stringhe a doppia quotatura separate da virgole. Per evitare qualsiasi doppiaquota visualizzata all'interno di un valore di colonna, vengono utilizzate doppie doppie virgolette. Le backslash possono rappresentare se stesse.

Ad esempio, la linea:

"", "\wave\", ""hello,"" said the vicar", "what are ""scare-quotes"" good for?", "I'm reading ""Bossypants""" 

se analizzato in JSON dovrebbe essere:

[ "", "\\wave\\", "\"hello,\" said the vicar", "what are \"scare-quotes\" good for?", "I'm reading \"Bossypants\"" ] 

Sto cercando di utilizzare il LOAD DATA per leggere il CSV in, ma sto correndo in qualche strano comportamento.


Come esempio, si consideri se ho una semplice tabella a due colonne

shell% mysql exampledb -e "describe person" 
+-------+-----------+------+-----+---------+-------+ 
| Field | Type  | Null | Key | Default | Extra | 
+-------+-----------+------+-----+---------+-------+ 
| ID | int(11) | YES |  | NULL |  | 
| UID | char(255) | YES |  | NULL |  | 
+-------+-----------+------+-----+---------+-------+ 
shell% 

Se la prima riga non-header del mio file di input termina "":

shell% cat temp-1.csv 
"ID","UID" 
"9","" 
"0","Steve the Pirate" 
"1","\Alpha" 
"2","Hoban ""Wash"" Washburne" 
"3","Pastor Veal" 
"4","Tucker" 
"10","" 
"5","Simon" 
"6","Sonny" 
"7","Wat\" 

I può caricare ogni riga non di intestazione ma il primo:

mysql> DELETE FROM person; 
Query OK, 0 rows affected (0.00 sec) 

mysql> LOAD DATA 
      LOCAL INFILE 'temp-1.csv' 
      INTO TABLE person 
      FIELDS 
      TERMINATED BY ',' 
      ENCLOSED BY '"' 
      ESCAPED BY '"' 
      LINES 
      TERMINATED BY '\n' 
      IGNORE 1 LINES 
     ; 
Query OK, 9 rows affected (0.00 sec) 
Records: 9 Deleted: 0 Skipped: 0 Warnings: 0 

mysql> SELECT * FROM person; 
+------+------------------------+ 
| ID | UID     | 
+------+------------------------+ 
| 0 | Steve the Pirate  | 
| 10 |      | 
| 1 | \Alpha     | 
| 2 | Hoban "Wash" Washburne | 
| 3 | Pastor Veal   | 
| 4 | Tucker     | 
| 5 | Simon     | 
| 6 | Sonny     | 
| 7 | Wat\     | 
+------+------------------------+ 
9 rows in set (0.00 sec) 

O posso caricare tutte le righe con l'indicazione dell'header:

mysql> DELETE FROM person; 
Query OK, 9 rows affected (0.00 sec) 

mysql> LOAD DATA 
      LOCAL INFILE 'temp-1.csv' 
      INTO TABLE person 
      FIELDS 
      TERMINATED BY ',' 
      ENCLOSED BY '"' 
      ESCAPED BY '"' 
      LINES 
      TERMINATED BY '\n' 
      IGNORE 0 LINES 
     ; 
Query OK, 11 rows affected, 1 warning (0.01 sec) 
Records: 11 Deleted: 0 Skipped: 0 Warnings: 1 

mysql> show warnings; 
+---------+------+--------------------------------------------------------+ 
| Level | Code | Message            | 
+---------+------+--------------------------------------------------------+ 
| Warning | 1366 | Incorrect integer value: 'ID' for column 'ID' at row 1 | 
+---------+------+--------------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> SELECT * FROM person; 
+------+------------------------+ 
| ID | UID     | 
+------+------------------------+ 
| 0 | UID     | 
| 9 |      | 
| 0 | Steve the Pirate  | 
| 10 |      | 
| 1 | \Alpha     | 
| 2 | Hoban "Wash" Washburne | 
| 3 | Pastor Veal   | 
| 4 | Tucker     | 
| 5 | Simon     | 
| 6 | Sonny     | 
| 7 | Wat\     | 
+------+------------------------+ 
11 rows in set (0.00 sec) 

Se nessuna linea della mia fine file di input su "":

shell% cat temp-2.csv 
"ID","UID" 
"0","Steve the Pirate" 
"1","\Alpha" 
"2","Hoban ""Wash"" Washburne" 
"3","Pastor Veal" 
"4","Tucker" 
"5","Simon" 
"6","Sonny" 
"7","Wat\" 

poi possibile caricare linee:

mysql> DELETE FROM person; 
Query OK, 11 rows affected (0.00 sec) 

mysql> LOAD DATA 
      LOCAL INFILE 'temp-2.csv' 
      INTO TABLE person 
      FIELDS 
      TERMINATED BY ',' 
      ENCLOSED BY '"' 
      ESCAPED BY '"' 
      LINES 
      TERMINATED BY '\n' 
      IGNORE 1 LINES 
     ; 
Query OK, 0 rows affected (0.00 sec) 
Records: 0 Deleted: 0 Skipped: 0 Warnings: 0 

mysql> SELECT * FROM person; 
Empty set (0.00 sec) 

Oppure posso caricare tutte le righe inclusa l'intestazione:

mysql> DELETE FROM person; 
Query OK, 0 rows affected (0.00 sec) 

mysql> LOAD DATA 
      LOCAL INFILE 'temp-2.csv' 
      INTO TABLE person 
      FIELDS 
      TERMINATED BY ',' 
      ENCLOSED BY '"' 
      ESCAPED BY '"' 
      LINES 
      TERMINATED BY '\n' 
      IGNORE 0 LINES 
     ; 
Query OK, 9 rows affected, 1 warning (0.03 sec) 
Records: 9 Deleted: 0 Skipped: 0 Warnings: 1 

mysql> show warnings; 
+---------+------+--------------------------------------------------------+ 
| Level | Code | Message            | 
+---------+------+--------------------------------------------------------+ 
| Warning | 1366 | Incorrect integer value: 'ID' for column 'ID' at row 1 | 
+---------+------+--------------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> SELECT * FROM person; 
+------+------------------------+ 
| ID | UID     | 
+------+------------------------+ 
| 0 | UID     | 
| 0 | Steve the Pirate  | 
| 1 | \Alpha     | 
| 2 | Hoban "Wash" Washburne | 
| 3 | Pastor Veal   | 
| 4 | Tucker     | 
| 5 | Simon     | 
| 6 | Sonny     | 
| 7 | Wat\     | 
+------+------------------------+ 
9 rows in set (0.00 sec) 

Così ora che ho scoperto molti modi per sbagliare, come posso usare LOAD DATA per importare i dati da questi file nel mio database?

risposta

15

Secondo the documentation for LOAD DATA, treating doubled double quotes as a double quote is the default:

Se il campo inizia con il carattere ENCLOSED BY, istanze di tale carattere sono riconosciuti come chiude un valore di campo solo se seguita dal campo o riga che termina con sequenza. Per evitare ambiguità, le occorrenze del carattere ENCLOSED BY all'interno di un valore di campo possono essere raddoppiate e interpretate come una singola istanza del carattere. Per esempio, se CHIUSA DA '"' è specificato, le virgolette sono gestite come illustrato di seguito:

"The ""BIG"" boss" -> The "BIG" boss 
The "BIG" boss  -> The "BIG" boss 
The ""BIG"" boss -> The ""BIG"" boss 

Quindi tutto quello che devi fare è disabilitare interpretare \ come carattere di escape, utilizzando ESCAPED BY ''.

LOAD DATA 
    LOCAL INFILE 'temp-1.csv' 
    INTO TABLE person 
    FIELDS 
    TERMINATED BY ',' 
    ENCLOSED BY '"' 
    ESCAPED BY '' 
    LINES 
    TERMINATED BY '\n' 
    IGNORE 1 LINES 
; 
+0

+1 Il tuo suggerimento mi ha aiutato a risolvere un altro problema. Avevo tutti i campi tra virgolette in un csv e se il campo era vuoto, il csv avrebbe semplicemente svuotato due virgolette doppie "" - si supponeva che fosse il carattere di escape e il mio comando di importazione dei dati non funzionava. Mettendo in fuga da "" ha fatto il lavoro. Grazie. – Aakash

+0

Ho dati che sono esattamente rfc 4180, in quanto non c'è carattere di escape. Se c'è una virgola in un campo, deve essere racchiusa tra virgolette. Il fare 'ESCAPED BY ''' funziona in questo caso? – CMCDragonkai

Problemi correlati