Articles avec #mysql tag

Publié le 19 Août 2013

MySQL ne fournit pas de syntax pour le FULL OUTER JOIN mais par contre on peut facilement obtenir le même résultat à l'aide d'un UNION.

SELECT a.*, b.* FROM a LEFT JOIN b USING (id)
UNION
SELECT a.*, b.* FROM b LEFT JOIN a USING (id);

Il est important de garder le même ordre des champs entre les 2 SELECT pour que MySQL supprime automatiquement les doublons lors du l'UNION.

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 2 Juin 2013

Lorsqu'on utilise la ligne de commande MySQL on peut facilement charger un fichier sql à l'aide de la commande source :

mysql> source mon_fichier.sql;

Le problème est qu'il faut connaître le répertoire de travail courant de MySQL pour pouvoir utilisé un chemin relatif.

Et bien c'est très facile grâce à la séquence d'échappement \! qui permet de lancer n'import quelle commande shell.

Ainsi :

mysql> \! pwd

permet de connaître le repertoire de travail.

Et surtout cette séquence d'échappement permet de lancer n'import quelle commande shell :

mysql> \! bash

permet  d'ouvrir un shell à l'interieur de MySQL

et 

mysql> \! vi mon_fichier.sql

permet même de modifier le fichier sans sortir de MySQL.

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

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.

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 22 Janvier 2013

On peut récupére la version de MySQL avec la commande suivante:

mysql> SHOW VARIABLES LIKE "%version%";

Ce qui donne:

+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| protocol_version        | 10                           |
| version                 | 5.1.40                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | unknown-linux-gnu            |
+-------------------------+------------------------------+

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 10 Janvier 2013

Pour ceux qui utilise MySQL vous êtes certainement amené à travailler avec la ligne de commande MySQL.

Il y a une commande très utile pour logger les actions effectuées (par exemple lors d'une intervention en production):

mysql> tee mysql-cli.log

Et oui c'est analogue à la commande tee de linux/unix. Il suffit de préciser le fichier dans lequel logger les actions.

Attention tout ce qui est affiché dans la console est aussi loggé dans le fichier (les commandes tapées mais aussi les résultats obtenus).

Bien pratique lors des appels supports!

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 3 Janvier 2013

Allez une petite astuce sympa pour bien commencer l'année pour ceux qui utilisent la ligne de commande MySQL.

Si vous faites des SELECT et que le résultat retourné contient beaucoup de ligne c'est assez pénible dans un terminal (surtout si vous travailler sur une machine à distance).

Evidemment on peut toujours ajouté un LIMIT 50; à la fin de la requête mais bon ... on a vite fait d'en oublier un.

Totu ça pour dire qu'on peut utiliser la commande pager qui permet de spécifier une commande à utiliser lors de l'affichage des résultats.

Par exemple:

mysql> pager more
PAGER set to 'more'

Cette commande permet d'utiliser more lors de l'affichage des résultats et donc on aura qu'un écran d'afficher.

On peut également utiliser grep pour filtrer les lignes à afficher, etc ...

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 2 Janvier 2013

Aujourd'hui j'ai besoin de modifier une clé primaire sur une table, autrement dit de supprimer l'existante puis d'en créer une nouvelle.

Le problème il y a un auto_increment sur le champ de la clé primaire qui empêche la suppression de celle-ci.

mysql> alter table ma_table drop primary key;
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

Et là solution est assez simple : tout d'abord supprimer l'auto-increment puis ensuite la clé primaire.

Pour supprimer l'auto-increment il faut changer la définition du champ avec un alter table.

mysql> alter table ma_table modify old_id bigint(20) unsigned not null;
Query OK, 0 rows affected (0.12 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table ma_table drop primary key;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

 

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 7 Décembre 2012

Aujourd'hui je veux créer une table temporaire avec un CREATE TABLE ... SELECT ...

Le truc c'est que je ne sais pas à l'avance la structure de la table car le SELECT est construit dynamiquement.

Le soucis c'est que dans un soucis de performance j'ai besoin d'ajouter un index (ou une clé primaire) sur la colonne id (qui elle, est toujours dans ma table).

Et bien on peut inclure la création de l'index dans la requête de création de la table comme ceci

CREATE TABLE ma_table (INDEX (id)) SELECT id, champ1, champ2 FROM une_autre_table;

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 6 Décembre 2012

Aujourd'hui j'ai une table toute simple avec 2 champs : id et nom.

Je veux que l'id s'auto-incrémente (comme avec l'auto-incrémente de MySQL) mais je veux aussi pouvoir réutiliser les ids non utilisés (après une suppression par exemple).

Voilà un exemple pour mieux comprendre:

actions autoincrement de MySQL ce que je veux
ajout de 'Alice' 1 1
ajout de 'Bob' 2 2
ajout de 'Charles' 3 3
suppression de 'Bob' 3 2
ajout de 'Daniel' 4 3

Avec l'auto-increment de MySQL j'obtiendrai:

+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  3 | Charles |
|  4 | Daniel  |
+----+---------+

alors que je veux :

+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  2 | Daniel  |
|  3 | Charles |
+----+---------+

Et bien c'est possible avec la requête suivante:

SELECT COALESCE(MIN(t1.id),0) + 1 AS id FROM ma_table t1 LEFT JOIN ma_table t2 ON (t2.id = t1.id+1) WHERE t2.id IS NULL;

Et si on veut faire l'insert et le select en une seule requête ça donne :

INSERT INTO ma_table SELECT COALESCE(MIN(t1.id),0) + 1 AS id, 'Edouard' FROM ma_table t1 LEFT JOIN ma_table t2 ON (t2.id = t1.id+1) WHERE t2.id IS NULL;

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 27 Novembre 2012

Pour connaître la taille des tables d'une base MySQL il suffit d'exécuter la commande :

show table status;

On obtient tout un tas d'information comme le nombre de ligne, la taille du fichier, le moteur de base utilisé, etc.

Toutes les infos sont dispos ici : http://dev.mysql.com/doc/refman/5.5/en/show-table-status.html

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0