it-swarm.com.de

PHP - Import der CSV-Datei in die mysql-Datenbank mit LOAD DATA INFILE

Ich habe eine solche CSV-Datei

Date,Name,Call Type,Number,Duration,Address,PostalCode,City,State,Country,Latitude,Longitude
"Sep-18-2013 01:53:45 PM","Unknown","outgoing call",'123456',"0 Secs","null","null","null","null","null",0.0,0.0,,,
"Sep-18-2013 01:54:14 PM","Unknown","outgoing call",'1234567890',"0 Secs","null","null","null","null","null",0.0,0.0,,,
"Sep-18-2013 01:54:37 PM","Unknown","outgoing call",'14772580369',"1 Secs","null","null","null","null","null",0.0,0.0,,,

und ich verwende den folgenden Code, um die Daten in die Datenbank einzufügen 

$sql = "LOAD DATA INFILE `detection.csv`
              INTO TABLE `calldetections`
              FIELDS TERMINATED BY '"[email protected]_escape_string(",").
             "` OPTIONALLY ENCLOSED BY `"[email protected]_escape_string("\"").
             "` OPTIONALLY ENCLOSED BY `"[email protected]_escape_string("\'").
             "` ESCAPED BY `"[email protected]_escape_string("\\").
              "` LINES TERMINATED BY `".",,,\\r\\n".
             "`IGNORE 1 LINES `"

             ."(`date`,`name`,`type`,`number`,`duration`,`addr`,`pin`,`city`,`state`,`country`,`lat`,`log`)";
      $res = @mysql_query($con,$sql); 

aber nichts wird eingefügt; wo ist der fehler

14
chimbu

Wenn Sie echo($sql); ausführen, bevor Sie es ausführen, wird die Syntax Ihrer Abfrage aus folgenden Gründen falsch sein:

  1. Dateiname sollte in Anführungszeichen und nicht in Backticks stehen, da es sich um ein String-Literal und nicht um einen Bezeichner handelt.

  2. Es ist absolut nicht erforderlich, mysql_escape_string() aufzurufen, um ein Trennzeichen in den Klauseln FIELDS TERMINATED BY und ENCLOSED BY und ESCAPED BY anzugeben.

  3. Sie überbieten Backticks. Da in Ihrem Fall keine reservierten Wörter verwendet werden, geben Sie sie alle auf. Sie fügen nur Unordnung hinzu.

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

  5. Sie können die Klausel ENCLOSED BY nur einmal verwenden. Sie müssen das Feld Number anders behandeln.

  6. Wenn Sie Ihre Beispielzeilen betrachten, benötigen Sie IMHO nicht ESCAPED BY. Wenn Sie das Gefühl haben, dass Sie es brauchen, verwenden Sie es wie folgt: ESCAPED BY '\\'.

Davon ausgehend 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)

IMHO müssen Sie beim Laden einige Felder umwandeln:

  1. wenn date in Ihrer Tabelle vom Datentyp datetime ist, muss er umgewandelt werden, andernfalls erhalten Sie eine Fehlermeldung 

    Falscher Datums-/Uhrzeitwert: "Sep-18-2013 13:53:45 PM" für Spalte "Datum" in Zeile 

  2. sie müssen mit einzelnen Qoutes um die Werte im Feld Number umgehen

  3. sie möchten "null"-Stringliteral wahrscheinlich in NULL für addr, pin, city, state, country-Spalten ändern

  4. wenn die Dauer immer in Sekunden ist, können Sie einen ganzzahligen Sekundenwert extrahieren und so in Ihrer Tabelle speichern, um die Dauerwerte später einfach zusammenfassen zu können.

Davon abgesehen sollte eine nützliche Version der Erklärung in 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 Rechner

 mysql> LOAD DATA INFILE '/tmp/detection.csv'
 -> INTO TABLE Anruferkennung 
 -> FELDER BEENDET DURCH ',' 
 -> OPTIONAL EINGESCHLOSSEN DURCH '"' 
 -> LINES DURCH ',\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 (BEIDE'\'' 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'); 
 Abfrage OK, 3 betroffene Zeilen (0,00 Sek.) 
 Datensätze: 3 Gelöscht: 0 Übersprungen: 0 Warnungen: 0 

 Mysql> Wählen Sie * aus den Anruferkennungen; 
 + --------------------- + ----- ---- + --------------- + ------------- + ---------- + ---- - + ------ + ------ + ------- + --------- + ------ + ------ +
 | Datum | Name | Typ | Nummer | Dauer | Addr | Pin | Stadt | Bundesland | Land | Lat | Log | 
 + --------------------- + --------- + ------------- - + ------------- + ---------- + ------ + ------ + ------ + - ------ + --------- + ------ + ------ + 
 | 2013-09-18 13:53:45 | Unbekannt | ausgehender Anruf | 123456 | 0 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0,0 | 
 | 2013-09-18 13:54:14 | Unbekannt | ausgehender Anruf | 1234567890 | 0 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0,0 | 
 | 2013-09-18 13:54:37 | Unbekannt | ausgehender Anruf | 14772580369 | 1 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0.0 | 
 + --------------------- + --------- + ------------ --- + ------------- + ---------- + ------ + ------ + ------ + ------- + --------- + ------ + ------ + 
 3 Reihen in Satz (0,00 s) 

Und schließlich sollte in php die Zuweisung einer Abfragezeichenfolge an die Variable $sql 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') ";
40
peterm

Füge mehr als 7000000 Datensätze in 1 Minute in die Datenbank ein (superschnelle Abfrage mit Berechnung)

    mysqli_query($cons, '
    LOAD DATA LOCAL INFILE "'.$file.'"
    INTO TABLE tablename
    FIELDS TERMINATED by \',\'
    LINES TERMINATED BY \'\n\'
    IGNORE 1 LINES
    (isbn10,isbn13,price,discount,free_stock,report,report_date)
     SET RRP = IF(discount = 0.00,price-price * 45/100,IF(discount = 0.01,price,IF(discount != 0.00,price-price * discount/100,@RRP))),
         RRP_nl = RRP * 1.44 + 8,
         RRP_bl = RRP * 1.44 + 8,
         ID = NULL
    ')or die(mysqli_error());
    $affected = (int) (mysqli_affected_rows($cons))-1; 
    $log->lwrite('Inventory.CSV to database:'. $affected.' record inserted successfully.');

RRP und RRP_nl und RRP_bl ist nicht in csv, aber wir berechnen das und nach dem Einfügen.

0
krunal panchal