Laravel9使用DB::raw执行分组SQL报MariaDB GROUP BY附近语法错误
问题排查与解决方案
你遇到的SQL单独执行正常但Laravel中运行报GROUP BY附近语法错误的问题,核心原因和修复方案如下:
- 首先修正错误的调用写法:
DB::select()本身就是用于执行原生SQL的方法,直接传入SQL字符串即可,不需要额外包裹DB::raw()。多余的DB::raw()包装会让Laravel将SQL语句当作表达式对象处理,可能引发解析异常,直接去掉外层DB::raw()即可。 - 替换字符串拼接为参数绑定:不要直接把
$siteId拼进SQL字符串,这种写法不仅有SQL注入风险,一旦参数携带不可见特殊字符(比如表单提交带入的换行、多余引号、全角字符等,普通打印可能无法识别),就会直接触发SQL语法错误。改成Laravel原生参数绑定的写法即可完全避免这类问题,修正后的代码示例:
$rawActive = " SELECT SBC.SITE, OPR.OPERATOR, COUNT(*) TMO_COUNT, DATE_FORMAT( TMO.TMO_DATE, '%m%Y' ) BULANTAHUN FROM TOP_TMO TMO INNER JOIN SUBSCRIBER SBC ON TMO.SUBSCRIBER_ID = SBC.ID INNER JOIN OPERATOR OPR ON SBC.SITE_ID = OPR.ID WHERE SBC.SITE_ID = ? GROUP BY DATE_FORMAT( TMO.DATE, '%m%Y') "; $queryAct = DB::select($rawActive, [$siteId]);
- 检查
strict配置的修改位置:Laravel 9 版本开始为MariaDB单独提供了独立的连接驱动配置,如果你项目中数据库连接用的是mariadb驱动,需要修改config/database.php中connections.mariadb数组下的strict => false,而不是只修改mysql连接下的配置。修改完成后必须执行php artisan config:clear清除配置缓存,否则修改不会生效。 - 修复GROUP BY逻辑不兼容问题:你的SELECT语句中查询了
SBC.SITE、OPR.OPERATOR两个非聚合字段,但GROUP BY仅按日期字段分组,当数据库开启ONLY_FULL_GROUP_BY模式(MariaDB默认开启)时,即便语法没有问题也会抛出SQL错误。两种修复方式二选一:- 把这两个非聚合字段也加入GROUP BY规则
- 用
ANY_VALUE()函数包裹这两个字段,例如ANY_VALUE(SBC.SITE) AS SITE、ANY_VALUE(OPR.OPERATOR) AS OPERATOR
- 额外注意:
- 统一SQL中的日期字段名,你当前代码SELECT部分用的是
TMO.TMO_DATE,GROUP BY部分用的是TMO.DATE,如果表中实际只有一个日期字段,需要统一字段名,否则会报字段不存在错误。 DATE是MySQL/MariaDB的保留关键字,如果你的TOP_TMO表中日期字段名确实是DATE,建议在SQL中用反引号包裹字段名,写成``TMO.`DATE```,避免关键字解析冲突。
- 统一SQL中的日期字段名,你当前代码SELECT部分用的是
按以上步骤修改时,优先替换参数绑定写法,90%以上的near 'GROUP BY'语法错误都是字符串拼接带入不可见字符导致的。
内容的提问来源于stack exchange,提问作者Hafid Maulana
相关产品推荐
相关产品推荐

