2013-06-11 23 views
7

Tôi có một loạt dữ liệu CSV mà tôi cần tải vào cơ sở dữ liệu MySQL. Vâng, CSV-ish, có lẽ. (chỉnh sửa: actually, it looks like the stuff described in RFC 4180)LOAD DATA từ tệp CSV nơi doublequote được sử dụng làm ký tự thoát

Mỗi hàng là danh sách các chuỗi được phân tách bằng dấu phẩy được phân tách bằng dấu phẩy. Để thoát khỏi bất kỳ doublequotes xuất hiện trong một giá trị cột, double doublequotes được sử dụng. Dấu gạch chéo ngược được phép đại diện cho chính chúng.

Ví dụ, dòng:

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

nếu phân tích thành JSON nên là:

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

Tôi đang cố gắng sử dụng LOAD DATA để đọc CSV trong, nhưng tôi đang chạy vào một số hành vi kỳ lạ.


Như một ví dụ, hãy xem xét nếu tôi có một bảng hai cột đơn giản

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

Nếu dòng phi tiêu đề đầu tiên của tập tin đầu vào của tôi kết thúc vào "":

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\" 

tôi có thể tải mọi dòng không phải tiêu đề nhưng trước tiên:

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) 

Hoặc tôi có thể tải tất cả các dòng trong đó có tiêu đề:

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) 

Nếu không có dòng file kết thúc đầu vào của tôi trên "":

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\" 

sau đó tôi có thể hoặc tải không đường:

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) 

Hoặc tôi có thể tải tất cả các dòng bao gồm tiêu đề:

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) 

Vì vậy, bây giờ tôi đã phát hiện ra nhiều cách để làm điều đó sai, làm thế nào tôi có thể sử dụng LOAD DATA để nhập dữ liệu từ các tệp này vào cơ sở dữ liệu của tôi?

Trả lời

15

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

Nếu trường bắt đầu với sự bao bọc bởi nhân vật, trường hợp của nhân vật được công nhận là chấm dứt một giá trị trường chỉ nếu tiếp theo là lĩnh vực hoặc đường chấm dứt bởi chuỗi. Để tránh sự mơ hồ, các lần xuất hiện của ký tự ENCLOSED BY trong một giá trị trường có thể được nhân đôi và được hiểu là một cá thể đơn lẻ của ký tự. Ví dụ, nếu được bao bọc bởi '"' được chỉ định, dấu ngoặc kép được xử lý như thể hiện ở đây:

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

Vì vậy, tất cả những gì cần làm là vô hiệu hóa việc giải thích \ như một nhân vật chạy thoát, bằng cách sử dụng 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 Đề xuất của bạn đã giúp tôi giải quyết thêm một vấn đề nữa. Tôi đã có tất cả các lĩnh vực trong dấu ngoặc kép trong một csv và nếu lĩnh vực này có sản phẩm nào, csv sẽ chỉ có hai dấu nháy kép "" - nó giả định nó là ký tự thoát và lệnh nhập dữ liệu của tôi không hoạt động. Đưa ESCAPED BY '' đã thực hiện công việc. Cảm ơn. – Aakash

+0

Tôi có dữ liệu chính xác là rfc 4180, vì không có ký tự thoát. Nếu có một dấu phẩy ở bên cạnh một trường, thì nó phải được đặt trong dấu ngoặc kép. Làm cho 'ESCAPED BY ''' hoạt động trong trường hợp này? – CMCDragonkai