sql >> Databasteknik >  >> RDS >> Mysql

PHP - Importera CSV-fil till mysql-databas med LOAD DATA INFILE

Om du skulle göra echo($sql); Innan du kör den skulle du se att syntaxen för din fråga är felaktig av följande skäl:

  1. Filnamn bör omges av citattecken snarare än backticks eftersom det är en bokstavlig sträng inte en identifierare.

  2. Det finns absolut inget behov av att anropa mysql_escape_string() för att ange en avgränsare i FIELDS TERMINATED BY och ENCLOSED BY och ESCAPED BY klausuler.

  3. Du överanvänder backticks. Faktum är att i ditt fall, eftersom det inte används några reserverade ord, avstår du från dem alla. De lägger bara till röran.

  4. I slutet av den allra första raden i din CSV-fil måste du ha ,,, eftersom du använder dem som en del av en linjeavgränsare. Om du inte gör det kommer du att hoppa över inte bara första raden utan även andra raden som innehåller data.

  5. Du kan inte använda ENCLOSED BY klausul mer än en gång. Du måste hantera Number fältet på ett annat sätt.

  6. När du tittar på dina exempelrader behöver du inte ESCAPED BY . Men om du känner att du behöver den, använd den så här ESCAPED BY '\\' .

Med det sagt kan ett syntaktiskt korrekt uttalande se ut så här

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 måste du IMHO förvandla en hel del fält medan du laddar dem:

  1. om date i din tabell är datetime datatyp så måste den omvandlas, annars får du ett felmeddelande

    Felaktigt datetime-värde:"Sep-18-2013 01:53:45 PM" för kolumnen "date" på rad

  2. du måste hantera enstaka citat kring värden i Number fältet

  3. du vill troligen ändra "null" sträng bokstavlig till faktisk NULL för addr, pin, city, state, country kolumner

  4. om varaktigheten alltid är i sekunder kan du extrahera ett heltalsvärde på sekunder och lagra det på det sättet i din tabell för att enkelt kunna aggregera varaktighetsvärden senare.

Med det sagt borde en användbar version av uttalandet se ut ungefär så här

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

Nedan är resultatet av att köra frågan på min dator

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)

Och slutligen i php tilldela en frågesträng till $sql variabel bör se ut så här

$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. SQL Server prestanda råd från Brent Ozar och Pinal Dave

  2. Vad är databastestning och hur gör man det?

  3. Lagrad procedur för att ta bort dubbletter av poster i SQL-tabell

  4. Rekommenderat sätt / beställning att läsa data från en webbtjänst, analysera den data och infoga den i en SQLite db