Mysql
 sql >> Baza danych >  >> RDS >> Mysql

PHP - Importuj plik CSV do bazy danych mysql za pomocą funkcji LOAD DATA INFILE

Gdybyś zrobił echo($sql); zanim go wykonasz, zobaczysz, że składnia twojego zapytania jest nieprawidłowa z następujących powodów:

  1. Nazwa pliku powinna być ujęta w cudzysłów, a nie w znaki wsteczne, ponieważ jest to literał ciągu, a nie identyfikator.

  2. Absolutnie nie ma potrzeby wywoływania mysql_escape_string() aby określić ogranicznik w FIELDS TERMINATED BY i ENCLOSED BY i ESCAPED BY klauzule.

  3. Nadużywasz backticków. W rzeczywistości w twoim przypadku, ponieważ nie używa się żadnych zastrzeżonych słów, porzucasz je wszystkie. Dodają tylko bałaganu.

  4. Na końcu pierwszego wiersza pliku CSV, który musisz mieć ,,, ponieważ używasz ich jako części separatora linii. Jeśli tego nie zrobisz, pominiesz nie tylko pierwszą linię, ale także drugą, która zawiera dane.

  5. Nie możesz użyć ENCLOSED BY klauzula więcej niż raz. Masz do czynienia z Number pole w inny sposób.

  6. Patrząc na przykładowe wiersze IMHO, nie potrzebujesz ESCAPED BY . Ale jeśli czujesz, że tego potrzebujesz, użyj go w ten sposób ESCAPED BY '\\' .

Biorąc to pod uwagę, poprawne składniowo stwierdzenie może wyglądać tak

LOAD DATA INFILE 'detection.csv'
INTO TABLE calldetections
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY ',,,\r\n'
IGNORE 1 LINES 
(date, name, type, number, duration, addr, pin, city, state, country, lat, log)

Teraz IMHO musisz przekształcić sporo pól podczas ich ładowania:

  1. jeśli date w Twojej tabeli jest z datetime typ danych to musi zostać przekształcony, w przeciwnym razie pojawi się błąd

    Nieprawidłowa wartość datetime:„Sep-18-2013 01:53:45 PM” dla kolumny „date” w wierszu

  2. masz do czynienia z pojedynczymi cytatami wokół wartości w Number pole

  3. najprawdopodobniej chcesz zmienić "null" literał ciągu do rzeczywistego NULL dla addr, pin, city, state, country kolumny

  4. jeśli czas trwania jest zawsze wyrażony w sekundach, możesz wyodrębnić całkowitą wartość sekund i zapisać ją w ten sposób w tabeli, aby móc później łatwo agregować wartości czasu trwania.

Biorąc to pod uwagę, użyteczna wersja oświadczenia powinna wyglądać mniej więcej tak

LOAD DATA INFILE 'detection.csv'
INTO TABLE calldetections
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY ',,,\r\n'
IGNORE 1 LINES 
(@date, name, type, @number, @duration, @addr, @pin, @city, @state, @country, lat, log)
SET date = STR_TO_DATE(@date, '%b-%d-%Y %h:%i:%s %p'),
    number = TRIM(BOTH '\'' FROM @number),
    duration = 1 * TRIM(TRAILING 'Secs' FROM @duration),
    addr = NULLIF(@addr, 'null'),
    pin  = NULLIF(@pin, 'null'),
    city = NULLIF(@city, 'null'),
    state = NULLIF(@state, 'null'),
    country = NULLIF(@country, 'null') 

Poniżej znajduje się wynik wykonania zapytania na moim komputerze

mysql> LOAD DATA INFILE '/tmp/detection.csv'
    -> INTO TABLE calldetections
    -> FIELDS TERMINATED BY ','
    -> OPTIONALLY ENCLOSED BY '"' 
    -> LINES TERMINATED BY ',,,\n'
    -> IGNORE 1 LINES 
    -> (@date, name, type, @number, @duration, @addr, @pin, @city, @state, @country, lat, log)
    -> SET date = STR_TO_DATE(@date, '%b-%d-%Y %h:%i:%s %p'),
    ->     number = TRIM(BOTH '\'' FROM @number),
    ->     duration = 1 * TRIM(TRAILING 'Secs' FROM @duration),
    ->     addr = NULLIF(@addr, 'null'),
    ->     pin  = NULLIF(@pin, 'null'),
    ->     city = NULLIF(@city, 'null'),
    ->     state = NULLIF(@state, 'null'),
    ->     country = NULLIF(@country, 'null');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

mysql> select * from calldetections;
+---------------------+---------+---------------+-------------+----------+------+------+------+-------+---------+------+------+
| date                | name    | type          | number      | duration | addr | pin  | city | state | country | lat  | log  |
+---------------------+---------+---------------+-------------+----------+------+------+------+-------+---------+------+------+
| 2013-09-18 13:53:45 | Unknown | outgoing call | 123456      |        0 | NULL | NULL | NULL | NULL  | NULL    | 0.0  | 0.0  |
| 2013-09-18 13:54:14 | Unknown | outgoing call | 1234567890  |        0 | NULL | NULL | NULL | NULL  | NULL    | 0.0  | 0.0  |
| 2013-09-18 13:54:37 | Unknown | outgoing call | 14772580369 |        1 | NULL | NULL | NULL | NULL  | NULL    | 0.0  | 0.0  |
+---------------------+---------+---------------+-------------+----------+------+------+------+-------+---------+------+------+
3 rows in set (0.00 sec)

I wreszcie w php przypisując ciąg zapytania do $sql zmienna powinna wyglądać tak

$sql = "LOAD DATA INFILE 'detection.csv'
        INTO TABLE calldetections
        FIELDS TERMINATED BY ','
        OPTIONALLY ENCLOSED BY '\"' 
        LINES TERMINATED BY ',,,\\r\\n'
        IGNORE 1 LINES 
        (@date, name, type, @number, @duration, @addr, @pin, @city, @state, @country, lat, log)
        SET date = STR_TO_DATE(@date, '%b-%d-%Y %h:%i:%s %p'),
            number = TRIM(BOTH '\'' FROM @number),
            duration = 1 * TRIM(TRAILING 'Secs' FROM @duration),
            addr = NULLIF(@addr, 'null'),
            pin  = NULLIF(@pin, 'null'),
            city = NULLIF(@city, 'null'),
            state = NULLIF(@state, 'null'),
            country = NULLIF(@country, 'null') ";


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Samouczek oceny gwiazdek Jquery za pomocą php i mysql

  2. Czy moje połączenia z serwerem MySQL są szyfrowane i bezpieczne?

  3. Jak tworzyć relacje w MySQL

  4. Jak dodać niestandardowe ograniczenie CHECK w tabeli MySQL?

  5. 9 naprawdę przydatnych funkcji daty MySQL, które są łatwe do zapamiętania