Insertion CSV dans une bdd capricieuse

a marqué ce sujet comme résolu.

Bonjour,

J’essaye d’uploader un fichier CSV pour mettre à jour une bdd MySQL

J’ai déjà fait la partie "upload" mais quand j’essaye d’insérer le contenu du CSV dans la base, ça ne marche pas et ça ne montre aucune erreur (ou alors je ne sais pas les afficher).

Ce qui est bizarre, c’est que quand j’essaye exactement la même commande SQL dans l’interprète SQL de phpMyAdmin, la commande fonctionne et toutes les lignes sont insérées.

Voilà un extrait de mon code qui est censé insérer les lignes dans la base de données:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
echo "Transfert réussi";
//$connexion -> query('DELETE from bdd.table WHERE 1;');
$req=$connexion->query("
LOAD DATA INFILE '/tmp/uploaded/tmp.csv' INTO TABLE bdd.table
FIELDS ESCAPED BY '\\'
TERMINATED BY ';'
LINES TERMINATED BY '\r\n';");
if ($req){
    echo "<h2>Ajout dans la base de données effectué avec succès</h2>";
}
else{
    echo "ERREUR: Echec lors de l'ajout dans la base de données <br/>";
    var_dump($req);     
}
?>

Le fichier contient environ 16 000 lignes pour 3Mo.

Le fichier log d’erreur de php ne donne rien. J’ai déjà essayé de modifier le paramètre de LINES TERMINATED BY mais ça ne marche pas non plus.

Je précise que dans le script, je fait un chmod 777 sur le fichier /tmp/uploaded/tmp.csv avant l’exécution de la requête.

Je précise aussi qu’une fois le fichier uploadé sur le serveur, je ne le modifie jamais. Je ne fais que le déplacer dans le répertoire adéquat pour changer les permissions.

Merci par avance à ceux qui m’aideront

EDIT: Je n’arrive pas à colorer mon code, désolé pour vos yeux :euh:

+0 -0

Salut et merci pour ta réponse ! :)

C’est ce que je faisais au début de ma réflexion en fait, mais j’ai lu au cours de mes recherches qu’il était plus simple et surtout plus rapide de passer par SQL pour ce genre d’opération sur un grand nombre de ligne (les 16 000 étant amenées à évoluer, et j’aurais également un autre fichier de ~350 000 lignes à insérer ensuite, les performances sont donc importantes).

Si tu penses que ça ne jouera pas (ou très peu) sur les performances, j’utiliserai un array, mais par curiosité informatique j’aimerais quand même qu’on essaye de résoudre ce problème.

Alors, j’ai ajouté print_r($connexion->errorInfo()); juste sous le var_dump($req); et ça m’a donné l’erreur suivante:

Array ( [0] => 42000 [1] => 1083 [2] => Field separator argument is not what is expected; check the manual )

D’après mes (rapides) recherches, l’erreur est souvent provoquée quand on met deux doubles quotes au lieu d’une dans le FIELDS TERMINATED BY, ce qui n’est pas mon cas. Je n’ai pas encore poussé mes recherches plus loin car je voulais vous faire un rapport rapide (mais j’y vais de ce pas :-° )

PS: Pour la couleur c’est bien ce que j’avais fait, mais il fallait renseigner les balises <?php ... ?> dans le code :p

EDIT: J’ai un peu mis à jour mon code (enfin surtout ma requête) et j’ai désormais une autre erreur (pas très parlante malheureusement).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$req=$connexion->prepare("
LOAD DATA INFILE '/tmp/tmp.csv' 
INTO TABLE `bd.table`
FIELDS 
    TERMINATED BY ';'
    ESCAPED BY '\\'
LINES 
    TERMINATED BY '\n';");

$req->execute();
var_dump($req); 
/*
 * object(PDOStatement)#2 (1) { ["queryString"]=> string(180) " LOAD DATA INFILE '/tmp/tmp.csv' INTO TABLE
 * `bdd.table` FIELDS TERMINATED BY ';' ESCAPED BY '\' LINES TERMINATED BY ' ';" } 
*/

print_r($req->errorInfo());
/*
 * Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that 
 * corresponds to your MySQL server version for the right syntax to use near ''' at line 6 )
*/
?>

Du coup le problème viendrait du LINES TERMINATED BY ?

EDIT EDIT:

En enlevant le ESCAPED BY '\\' ça fonctionne ! Du coup j’ai un code rapide et fonctionnel, mais j’aimerais quand même essayer de comprendre la cause de l’erreur, et surtout à quoi ça sert de renseigner un caractère d’échappement si SQL est capable de le détecter tout seul ! :lol: (les lignes insérées contenant des quotes sont correctement échappées).

Pour ceux qui seraient dans la même problématique voici ma requête fonctionnelle (le reste du code n’a pas bougé):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
$req=$connexion->prepare("
LOAD DATA INFILE '/tmp/tmp.csv' 
INTO TABLE `table`
FIELDS 
    TERMINATED BY ';'

LINES 
    TERMINATED BY '\r\n';");
//var_dump($req);
$req->execute();
?>
+1 -0

Bonjour :)

En enlevant le ESCAPED BY '\\' ça fonctionne ! Du coup j’ai un code rapide et fonctionnel, mais j’aimerais quand même essayer de comprendre la cause de l’erreur, et surtout à quoi ça sert de renseigner un caractère d’échappement si SQL est capable de le détecter tout seul ! :lol: (les lignes insérées contenant des quotes sont correctement échappées).

Je pense que la valeur par défaut te convient, c’est aussi simple que ça. Si tu voulais échapper avec un autre caractère, là il faudrait utiliser l’option.

Quant à l’erreur, elle est rigolote !

Quand tu écris la chaîne PHP suivante :

1
2
<?php
"ESCAPED BY '\\'"

Le \\ est interprété par PHP comme le caractère \ qui a lui même été échappé par le second \. Le texte envoyé à MySQL est donc : ESCAPED BY '\'. Or, MySQL interprète \' comme un caractère ' (' étant le délimiteur de chaine, on l’échappe ici aussi avec \). Donc '\' sera interprété par MySQL comme le caractère de délimiteur de chaine ', puis le caractère textuel '. Il manque donc le délimiteur de fin de chaine et tu obtiens une erreur de syntaxe.

Je dirais qu’il faut écrire ESCAPED BY '\\\\' pour que ça fonctionne si tu tiens à expliciter le paramètre d’échappement. Ainsi, PHP interprète la chaine littérale avec la valeur '\\', qui est interprétée par MySQL comme le caractère de délimiteur de chaine ', puis le caractère textuel \, puis le caractère de délimiteur de chaine '.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte