Mysql
 sql >> Datenbank >  >> RDS >> Mysql

PHP - CSV-Datei mit LOAD DATA INFILE in die MySQL-Datenbank importieren

Wenn Sie echo($sql); ausführen würden Bevor Sie es ausführen, sehen Sie, dass die Syntax Ihrer Abfrage aus folgenden Gründen falsch ist:

  1. Der Dateiname sollte in Anführungszeichen und nicht in Backticks eingeschlossen werden, da es sich um ein Zeichenfolgenliteral und nicht um einen Bezeichner handelt.

  2. Es besteht absolut keine Notwendigkeit, mysql_escape_string() aufzurufen um ein Trennzeichen in FIELDS TERMINATED BY anzugeben und ENCLOSED BY und ESCAPED BY Klauseln.

  3. Sie verwenden zu viele Backticks. In Ihrem Fall lassen Sie sie alle fallen, da keine reservierten Wörter verwendet werden. Sie fügen nur Unordnung hinzu.

  4. Am Ende der allerersten Zeile Ihrer CSV-Datei müssen Sie haben ,,, weil Sie sie als Teil eines Zeilentrennzeichens verwenden. Wenn Sie das nicht tun, überspringen Sie nicht nur die erste Zeile, sondern auch die zweite, die Daten enthält.

  5. Sie können ENCLOSED BY nicht verwenden Klausel mehr als einmal. Sie müssen sich mit Number befassen Feld anders.

  6. Wenn Sie sich Ihre Beispielzeilen ansehen, brauchen Sie IMHO nicht ESCAPED BY . Aber wenn Sie das Gefühl haben, dass Sie es brauchen, verwenden Sie es so ESCAPED BY '\\' .

Davon abgesehen könnte eine syntaktisch korrekte Aussage so aussehen

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)

Jetzt müssen Sie IMHO einige Felder umwandeln, während Sie sie laden:

  1. wenn date in Ihrer Tabelle ist datetime Datentyp muss transformiert werden, andernfalls erhalten Sie einen Fehler

    Falscher datetime-Wert:„Sep-18-2013 01:53:45 PM“ für Spalte „date“ in Zeile

  2. Sie müssen sich mit einzelnen Anführungszeichen um Werte in Number befassen Feld

  3. Sie möchten höchstwahrscheinlich "null" ändern String-Literal zum tatsächlichen NULL für addr, pin, city, state, country Spalten

  4. Wenn die Dauer immer in Sekunden angegeben wird, können Sie einen ganzzahligen Sekundenwert extrahieren und auf diese Weise in Ihrer Tabelle speichern, um die Dauerwerte später einfach zusammenfassen zu können.

Davon abgesehen sollte eine nützliche Version der Anweisung etwa so aussehen

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') 

Unten ist das Ergebnis der Ausführung der Abfrage auf meinem Computer

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)

Und schließlich in PHP eine Abfragezeichenfolge $sql zuweisen Variable sollte so aussehen

$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') ";