关于laravel解决mysql only_full_group_by问题
下面由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 的任何配置
以上是关于laravel解决mysql only_full_group_by问题的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Laravel邮件发送失败时的退信代码获取方法在使用Laravel开发应用时,经常会遇到需要发送验证码的情况。而在实�...

Laravel计划任务运行无响应排查在使用Laravel的计划任务调度时,不少开发者会遇到这样的问题:schedule:run...

在dcatadmin(laravel-admin)中如何实现自定义点击添加数据的表格功能在使用dcat...

Laravel - 转储服务器 - Laravel 转储服务器随 Laravel 5.7 版本一起提供。以前的版本不包括任何转储服务器。转储服务器将成为 laravel/laravel Composer 文件中的开发依赖项。

Laravel框架中Redis连接的共享与select方法的影响在使用Laravel框架和Redis时,开发者可能会遇到一个问题:通过配置...

在Laravel多租户扩展包stancl/tenancy中自定义租户数据库连接使用Laravel多租户扩展包stancl/tenancy构建多租户应用时,...

Laravel - Action URL - Laravel 5.7 引入了一项名为“可调用操作 URL”的新功能。此功能类似于 Laravel 5.6 中的功能,即在操作方法中接受字符串。 Laravel 5.7 引入新语法的主要目的是直接
