Comment charger un fichier csv dans une table MySQL

Publié le 26 Février 2013

Il faut d'abord télécharger le fichier à l'aide d'un formulaire HTML.

Ensuite il faut récupérer le fichier avec du PHP et l'enregistrer dans un dossier.

Après il y a une commande MySQL qui permet de charger directement le contenu d'un fichier dans une table sans effectuer des INSERT:

LOAD DATA INFILE 'monfichier.csv' INTO TABLE ma_table fields terminated by ';';

Si tous les champs ne sont pas présent on peut éventuellement rajouter la liste des champs entre parenthèses à la fin de la requête.

Sous Ubuntu il y a qq soucis de sécurité car le process mysqld est surveillé par apparmor. MySQL se plaindra de ne pas trouver le fichier importé:

ERROR 13 (HY000): Can't get stat of '/root/api.csv' (Errcode: 13)

Pour le vérifier il faut utiliser:

sudo aa-status

5 processes are in enforce mode.
   /sbin/dhclient (2203)
   /usr/bin/evince (3641)
   /usr/lib/telepathy/mission-control-5 (2911)
   /usr/sbin/cupsd (1066)
   /usr/sbin/mysqld (6970) 

MySQL est bien en 'enforce' mode. Il faut donc modifier la config apparmor pour donner acces en lecture aux fichiers importés pour mysql:

sudo vi /etc/apparmor.d/usr.sbin.mysqld

Ensuite il faut ajouter 2 lignes à la fin du fichier (avant l'accolade de fermeture)

 /var/www/mon_site/import/ r,
 /var/www/mon_site/import/* r,

Bien sûr /var/www/mon_site/import est le dossier dans lequel j'enregistre les fichiers CSV téléchargés.

Ensuite il faut recharger la config d'apparmor:

sudo /etc/init.d/apparmor reload

Maintenant le LOAD DATA INFILE devrait fonctionner sinon il faut vérifier les privilèges mysql.

Par exemple l'erreur:

ERROR 1045 (28000): Access denied for user

se résout en ajoutant le privilège "FILE" avec la commande suivante:

GRANT FILE ON *.* TO 'my_user'@'localhost';

Dans les versions précédentes de MySQL il était possible de contourner le problème en utilisant un LOAD DATA LOCAL INFILE mais désormais cette option est désactivé par défaut. Il faut préciser --local-infile=0 sur la ligne de commande pour démarrer mysql.

LOAD DATA INFILE signifie que le fichier à charger se trouve sur le serveur MySQL.

LOAD DATA LOCAL INFILE signifie que le fichier se trouve du côté du client MySQL et que c'est ce dernier qui l'enverra au serveur.

Pour ma part PHP et MySQL tournent sur la même machine mais attention si ce n'est pas le cas.

Rédigé par Bliz

Publié dans #MySQL

Repost 0
Commenter cet article