J'ai un fichier .csv comme ça
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,,,
et j'utilise le code suivant pour insérer les données dans la base de données
$sql = "LOAD DATA INFILE `detection.csv`
INTO TABLE `calldetections`
FIELDS TERMINATED BY '".@mysql_escape_string(",").
"` OPTIONALLY ENCLOSED BY `".@mysql_escape_string("\"").
"` OPTIONALLY ENCLOSED BY `".@mysql_escape_string("\'").
"` ESCAPED BY `".@mysql_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);
mais rien n'est inséré; où est l'erreur?
Si vous exécutiez echo($sql);
avant de l'exécuter, la syntaxe de votre requête serait incorrecte pour les raisons suivantes:
Le nom de fichier doit être placé entre guillemets et non entre guillemets car c'est un littéral de chaîne et non un identifiant.
Il n'est absolument pas nécessaire d'appeler mysql_escape_string()
pour spécifier un délimiteur dans les clauses FIELDS TERMINATED BY
et ENCLOSED BY
et ESCAPED BY
.
Vous abusez des backticks. En fait, dans votre cas, comme aucun mot réservé n’est utilisé, vous les abandonnez tous. Ils ne font qu'ajouter de l'encombrement.
À la fin de la toute première ligne de votre fichier CSV, vous devez disposer de,,,
car vous les utilisez dans le cadre d'un séparateur de ligne. Si vous ne le faites pas, vous passerez non seulement à la première ligne, mais également à la seconde qui contient des données.
Vous ne pouvez pas utiliser la clause ENCLOSED BY
plus d'une fois. Vous devez traiter le champ Number
d'une manière différente.
En regardant vos exemples de lignes IMHO, vous n'avez pas besoin de ESCAPED BY
. Mais si vous sentez que vous en avez besoin, utilisez-le comme ceci ESCAPED BY '\\'
.
Cela étant dit, une déclaration syntaxiquement correcte pourrait ressembler à ceci
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)
Maintenant, à mon humble avis, vous devez transformer plusieurs champs pendant que vous les chargez:
si date
dans votre table est du type de données datetime
, il doit être transformé, sinon vous obtiendrez une erreur.
Valeur de date/heure incorrecte: 'Sep-18-2013 01:53:45 PM' pour la colonne 'date' à la ligne
vous devez traiter avec des qoutes simples autour des valeurs dans le champ Number
vous voudrez probablement changer la chaîne "null"
en littéral NULL
pour les colonnes addr, pin, city, state, country
si la durée est toujours en secondes, vous pouvez extraire une valeur entière de secondes et la stocker ainsi dans votre table pour pouvoir facilement agréger les valeurs de durée ultérieurement.
Cela étant dit, une version utile de la déclaration devrait ressembler à ceci:
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')
Voici le résultat de l'exécution de la requête sur ma machine
mysql> LOAD DATA INFILE '/tmp/detection.csv' -> INTO TABLEdetections d'appels -> ZONES TERMINÉES PAR ',' -> OPTIONNELLEMENT FERMÉ PAR '' '' -> LIGNES TERMINÉES PAR ',\n' -> IGNORER 1 LIGNES -. (@Date, nom, type, @numéro, @durée, @addr, @pin, @city, @state, @country, lat, log) -> SET date = STR_TO_DATE (@date, '% b-% d-% Y% h:% i:% s% p '), -> nombre = TRIM (BOTH'\'' FROM @number), -> duration = 1 * TRIM (TRAILING 'Secs' FROM @duration), -> addr = NULLIF (@addr, 'null'), -> pin = NULLIF (@pin, 'null'), -> ville = NULLIF (@city, 'null'), -> état = NULLIF (@state, 'null'), -> country = NULLIF (@country, 'null'); Requête OK, 3 lignes affectées (0,00 s) .__ Enregistrements: 3 Supprimés: 0 Skipped: 0 Avertissements: 0 Mysql> select * from calldetections; + --------------------- + ----- ---- + --------------- + ------------- + ---------- + ---- - + ------ + ------ + ------- + --------- + ------ + ------ + | date | nom | type | numéro | durée | addr | épingle | ville | état | pays | lat | journal | + --------------------- + --------- + ------------- - + ------------- + ---------- + ------ + ------ + ------ + - ------ + --------- + ------ + ------ + | 2013-09-18 13:53:45 | Inconnu | appel sortant | 123456 | 0 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0,0 | | 2013-09-18 13:54:14 | Inconnu | appel sortant | 1234567890 | 0 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0,0 | | 2013-09-18 13:54:37 | Inconnu | appel sortant | 14772580369 | 1 | NULL | NULL | NULL | NULL | NULL | 0,0 | 0.0 | + --------------------- + --------- + ------------ --- + ------------- + ---------- + ------ + ------ + ------ + ------- + --------- + ------ + ------ + 3 rangées dans le jeu (0.00 sec)
Et enfin en php assigner une chaîne de requête à la variable $sql
devrait ressembler à ceci
$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') ";
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 et RRP_nl et RRP_bl ne sont pas dans csv mais nous calculons cela et après l'insérons.