Maison  >  Article  >  cadre php  >  À propos de Laravel résolvant le problème MySQL only_full_group_by

À propos de Laravel résolvant le problème MySQL only_full_group_by

藏色散人
藏色散人avant
2021-01-25 13:44:093003parcourir
Vous trouverez ci-dessous

Tutoriel Laravel colonne pour présenter la méthode de résolution de MySQL par Laravel only_full_group_by. J'espère que cela sera utile aux amis qui en ont besoin !

Après MySQL 5.7, only_full_group_by est activé par défaut, ce qui conduit à une détection SQL plus stricte, ce qui entraînera le signalement de l'erreur suivante

SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'edu.t_sounds.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Il n'y a aucun moyen pour résoudre ce problème. Évitez les détours et essayez un par un selon les méthodes trouvées en ligne

Idées de solutions

Voir sql_mode

select @@GLOBAL.sql_mode;SELECT @@SESSION.sql_mode

Vérifiez et modifiez d'abord le fichier de configuration mysql. My.cnf est très embarrassant. Il n'y a pas de ONLY_FULL_GROUP_BY dans my.cnf. Selon la configuration du client, ajoutez la configuration [client]
[mysqld]sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
<.>Redémarrez MySQL, vérifiez sql_mode dans l'outil MySQL, cela montre que le résultat est le même que la configuration, mais le programme signale toujours la même erreur

Après une nouvelle recherche, j'ai J'ai soudainement réalisé le problème de la session globale, c'est-à-dire les deux instructions pour interroger sql_mode en tête de l'article, j'ai donc demandé quelle était la différence

paramètres des variables mysql Il existe deux manières,

un global une configuration, c'est-à-dire globale, qui agit sur le monde entier ;

une configuration de session, qui n'agit que sur la connexion en cours

Est-ce que ce sera possible ? sql_mode

dans la connexion actuelle Lorsque le programme laravel imprime sql_mode

[client]sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

, il s'avère que c'est le programme qui le définit

. La première chose qui me vient à l'esprit est mysql. Il y a un mode strict dans la configuration, je l'ai toujours activé et je l'ai défini sur false. Le problème a été résolu avec succès

$result = \DB::select(&#39;SELECT @@GLOBAL.sql_mode&#39;);
print_r($result);exit;
结果:
STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

$result = \DB::select(&#39;SELECT @@SESSION.sql_mode&#39;);
print_r($result);exit;
结果:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Cela peut résoudre le problème. problème, mais basé sur la technologie, je veux juste comprendre comment il est écrit, et je ne veux pas le définir directement sur false,

Recherchez strict dans le fournisseur/laravel/framework /src/ILLumate/Database, et trouvez directement le code principal

    fichier : supplier/laravel/ framework/src/ILLumate/Database/Connectors/MySqlConnector.php
  • 'strict' => false,
  • Le premier jugement directement détermine s'il existe une configuration de modes. Si c'est le cas, utilisez simplement ceci

pour le faire

protected function setModes(PDO $connection, array $config){
    if (isset($config['modes'])) {
        $this->setCustomModes($connection, $config);
    } elseif (isset($config['strict'])) {
        if ($config['strict']) {
            $connection->prepare($this->strictMode($connection))->execute();
        } else {
            $connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
        }
    }}

Testez et résolvez le problème directement

Dans l'esprit de la recherche racine, continuons la lecture

Si strict = true

sera défini directement dans le programme sql_mode codé en dur, laravel distingue mysql 8.0.11 des autres versions

'modes' => ['STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'ERROR_FOR_pISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION'],

Puis si strict = false, définissez directement sql_mode sur NO_ENGINE_SUBSTITUTION

protected function strictMode(PDO $connection)
{
    if (version_compare($connection->getAttribute(PDO::ATTR_SERVER_VERSION), &#39;8.0.11&#39;) >= 0) {
        return "set session sql_mode=&#39;ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION&#39;";
    }

    return "set session sql_mode=&#39;ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION&#39;";
}

Le problème est complètement résolu ici

La solution finale

$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();

conservé strict = true et ajouté l'option modes Les paramètres à l'intérieur. sont la configuration sous-jacente de laravel, mais seulement supprimés ONLY_FULL_GROUP_BY

Résumé : Après avoir fait de nombreux détours et passé beaucoup de temps, le problème a finalement été résolu et il n'a pas été nécessaire de modifier quoi que ce soit. configuration de mysql

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer