Si vous êtes sur cette page c’est que vous avez rencontré une erreur avec la version 5.7 de MySQL ! (Je suis sous OSX Mojave, aussi cette solution est significative pour les Mac, mais aussi pour Linux)
Contenu
Pourquoi avez vous cette erreur ?
Dans la version 5.7 de MySQL, lorsque vous faites une aggrégation de colonne, vous devez spécifier explicitement le nom de la colonne à aggréger dans le SELECT sinon vous aurez cette erreur. Parce que par défaut dans cette nouvelle version on interdit des GROUP BY implicite. Normalement le GROUP BY ne peut se faire que sur des noms de colonnes agrégées par une des 5 fonctions d’aggrégation suivantes : SUM
, COUNT
, MAX
, MIN
, AVERAGE
.
Il y a une variable qui s’appelle sqlmode
, et conditionne le fonctionnement des requêtes SQL. Par défaut sont contenu est :
ONLY_FULL_GROUP_BY,NO_AUTO_CREATE_USER,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
En premier on a ONLY_FULL_GROUP_BY
, c’est elle qui nous intéresse. Il faut le supprimer pour vous puissiez faire des GROUP BY
implicite. Qu’est-ce qu’un GROUP BY
implicite? Imaginez que vous avez la requête suivante
SELECT id, username FROM user GROUP BY id
Sur la requête ci-dessus, on groupe sur la colonne id, or il n’y aucune fonction d’aggrégation. Donc ceci n’est plus permis, à moins de faire un petit réglage dans le fichier de configuration my.cnf un peu plus loin.
Voici une requête plus propre :
SELECT count(amount) AS total, customer FROM order GROUP BY total
Dans la requête ci-dessus, la colonne avec l’alias total est une colonne agrégée, donc le group by sur cette colonne est tout à fait explicite, avec la nouvelle version de MySQL elle passera sans problème. C’est d’ailleurs comme ça que j’avais appris.
Comment résoudre cette erreur ?
Dans la configuration de MySQL 5.7, il faut trouver la variable qui permet de configurer soit en runtime soit au démarrage (et ce de façon permanente) le comportement de votre base de données favorite.
La façon runtime (ne marche pas pour moi)
Vous pouvez faire cette requête dans la console MySQL pour montrer le contenu de la variable sql_mode:
SELECT @@sql_mode > STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Jouez cette requête pour modifier la variable, le but étant de supprimer le ONLY_FULL_GROUP_BY
et de garder le reste, je tiens à préciser que cette méthode n’a pas marché pour moi, néanmoins marche dans pour les requêtes dans MySQLWorkbench.
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
La façon permanente
Le mieux est de modifier le fichier my.cnf
, et de redémarrer MySQL. Donc éditez le fichier my.cnf
qui se trouve dans /etc
pour Linux et MacOS en insérant cette ligne dans la section [mysqld]
:
[mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Redémarrer MySQL sur Linux (Debian, Ubuntu)
sudo /etc/init.d/mysql restart ou service mysqld restart
Redémarrer MySQL sur MacOS
J’ai eu plus de difficulté, en effet sur le Net, on trouve souvent cette commande :
sudo /usr/local/mysql/support-files/mysql.server restart
Si elle ne marche pas, je pense si vous avez installé MySQL avec Homebrew, il faut localiser le répertoire de MySQL, pour ma part sous Mojave il se trouve dans le répertoire /usr/local/Cellar/mysql@5.7/5.7.26/support-files/mysql.server
:
sudo /usr/local/Cellar/mysql@5.7/5.7.26/support-files/mysql.server restart
Pourquoi ne pas modifier les requêtes SQL pour les mettre à jour?
C’est possible, mais vous n’avez pas forcément le temps de le faire, aussi j’ai choisi cette solution.
Note :
J’ai perdu pas mal de temps avec PDO, n’ayant pas les affichages d’erreurs, juste après la requête, vous pouvez retourner le code erreur donné par PDO, il faut absolument le faire car PDO peut planter sans broncher, et le mettre dans le bloc try ... catch
ne suffit pas à lancer une PDOException
(du moins dans mes réglages à moi)
$stmt = $dbh->query($sql); $dbh->errorInfo();// tableau d'erreur très utile !