关于laravel解决mysql only_full_group_by问题

2022-05-15 0 129

下面由Laravel教程栏目给大家介绍laravel解决mysql only_full_group_by问题的方法,希望对需要的朋友有所帮助!

MySQL 5.7 之后 only_full_group_by 默认是开启的,这就导致 sql 的检测更加严格,将导致报下面的错

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

解决这个问题也走了不少弯路,按照网上找的方式一个一个试

解决思路

查看 sql_mode

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

首先查看并修改 mysql 配置文件,my.cnf 很尴尬我的这个里面并没有 ONLY_FULL_GROUP_BY

[mysqld]sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

不行,就接着来,想到mysql 有服务端配置,和客户端配置之分,那就增加 [client] 配置

[client]sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

重启mysql ,在MySQL工具查看 sql_mode,确实显示结果和配置的是一样的,但是程序依然报同样的错

又是一番查找,突然意识到 global session 的问题,也就是文章头部放的两条查询 sql_mode 的语句,就查询一下 是啥区别

mysql 变量设置方式分两种,
一种全局配置,也就是 global,作用于全局;
一种会话配置 session, 只作用于当前连接

会不会是laravel 在当前连接设置了 sql_mode

在 laravel 程序打印 sql_mode

$result = \\DB::select('SELECT @@GLOBAL.sql_mode');print_r($result);exit;结果:STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION$result = \\DB::select('SELECT @@SESSION.sql_mode');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

找到了原来是程序设置了

第一想到 mysql 的配置有一个严格模式,我一直是开启状态,设置为 false 问题顺利解决

'strict' => false,

这样可以解决问题,但本着技术就是要搞清楚到底是咋写的,也并不想直接给他设置为 false,

在 vendor/laravel/framework/src/ILLuminate/Database 文件夹下搜索 strict ,直接找到核心代码

文件:vendor/laravel/framework/src/ILLuminate/Database/Connectors/MySqlConnector.php

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();        }    }}

第一个判断直接判断是否存在 modes 配置,有的话就直接使用这个

来,搞一下

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

测试,直接问题搞定

本着寻根刨底的精神,再接着往下看

如果 strict = true

将直接设置程序中写死的 sql_mode, laravel 区分了 mysql 8.0.11 和别的版本

protected function strictMode(PDO $connection){    if (version_compare($connection->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11') >= 0) {        return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";    }    return "set session sql_mode='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'";}

再接着 如果 strict = false ,直接将 sql_mode 设置为NO_ENGINE_SUBSTITUTION

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

到这里问题就彻底解决了

最终解决方式

'strict' => true,'modes' => ['STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION'],

保留了 strict = true,增加 modes 选项,里面的参数是 laravel 底层的配置,只是去掉了 ONLY_FULL_GROUP_BY

总结:走了不少弯路,也花了不少时间,最终问题解决,并且并不需要修改 mysql 的任何配置

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

【声明:根据2013年1月30日《计算机软件保护条例》2次修订第17条规定: 为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存 储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬! 鉴于此,也希望大家按此说明研究软件!】
本站所有源码尽量保证原汁原味,如有特殊情况会作出声明及标注,网站资源不做任何二次加密(原版加密除外,不影响程序使用的不会做解密处理),方便您更好的学习参考。 在您的能力范围内,为了大环境的良性发展,请尽可能的选择正版资源。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

即刻码站__国内靠谱的站长资源下载平台 php教程 关于laravel解决mysql only_full_group_by问题 https://www.jike1995.com/36884.html

常见问题
  • 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度
查看详情

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务