sql >> Database >  >> RDS >> Mysql

PHP - CSV-bestand importeren in mysql-database met behulp van LOAD DATA INFILE

Als je echo($sql); . zou doen voordat u het uitvoert, ziet u dat de syntaxis van uw zoekopdracht om de volgende redenen onjuist is:

  1. Bestandsnaam moet tussen aanhalingstekens staan ​​in plaats van backticks, omdat het een letterlijke tekenreeks is en geen identifier.

  2. Het is absoluut niet nodig om mysql_escape_string() . aan te roepen om een ​​scheidingsteken op te geven in FIELDS TERMINATED BY en ENCLOSED BY en ESCAPED BY clausules.

  3. Je gebruikt te veel backticks. In jouw geval, aangezien er geen gereserveerde woorden worden gebruikt, gooi je ze allemaal weg. Ze voegen alleen maar rommel toe.

  4. Aan het einde van de allereerste regel van je CSV-bestand moet je moeten ,,, omdat je ze gebruikt als onderdeel van een lijnscheidingsteken. Als je dat niet doet, sla je niet alleen de eerste regel over, maar ook de tweede regel die gegevens bevat.

  5. Je kunt ENCLOSED BY niet gebruiken clausule meer dan eens. Je hebt te maken met Number veld op een andere manier.

  6. Als je naar je voorbeeldrijen kijkt, heb je IMHO ESCAPED BY niet nodig . Maar als je denkt dat je het nodig hebt, gebruik het dan als volgt ESCAPED BY '\\' .

Dat gezegd hebbende, zou een syntactisch correcte uitspraak er zo uit kunnen zien

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)

Nu moet je IMHO nogal wat velden transformeren terwijl je ze laadt:

  1. als date in je tabel is van datetime gegevenstype dan moet het worden getransformeerd, anders krijg je een foutmelding

    Onjuiste datetime-waarde:'Sep-18-2013 01:53:45 PM' voor kolom 'date' op rij

  2. je hebt te maken met enkele qoutes rond waarden in Number veld

  3. u wilt hoogstwaarschijnlijk "null" . wijzigen tekenreeks letterlijk naar feitelijk NULL voor addr, pin, city, state, country kolommen

  4. als de duur altijd in seconden is, kun je een geheel getal van seconden extraheren en op die manier in je tabel opslaan om later gemakkelijk de duurwaarden te kunnen aggregeren.

Dat gezegd hebbende, zou een bruikbare versie van de verklaring er ongeveer zo uit moeten zien

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

Hieronder staat het resultaat van het uitvoeren van de query op mijn 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)

En tot slot in php een queryreeks toewijzen aan $sql variabele zou er zo uit moeten zien

$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. Ongeldig syntaxisfouttype =MyISAM in DDL gegenereerd door Hibernate

  2. Application_name instellen op Postgres/SQLAlchemy

  3. Postgres-tijd met gelijkheid van tijdzone

  4. Selecteer de laatste rij voor elke groep van orakel