0

我的 PHP 应用程序出现以下错误:

不正确的 SQL 查询(数据库)在没有 GROUP BY 的聚合查询中,SELECT 列表的表达式 #1 包含非聚合列 'db_20172201.cm_order.buyer';这与 sql_mode=only_full_group_by 不兼容

环顾了一会,并在尝试识别导致此错误的查询后,我决定应该更改 MySQL 服务器中的 SQL_MODE 选项。

我做了两件事来做到这一点:

  • 执行了这个查询

    SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
    
  • 添加了以下内容,my.cnf其中是 MySQL 的配置文件

    [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"
    

我认为这些就足够了,但错误永远不会从我的应用程序中消失。当我SQL_MODE通过此查询检查环境中的值时

SELECT @@GLOBAL.sql_mode

它显示了上面插入的值。

我不知道还能去哪里看。我还尝试在执行查询之前从我的应用程序中设置 sql_mode 变量,但没有解决。

- - 更新

我刚刚在我的应用程序中打印了查询的结果,结果SELECT @@SESSION.SQL_MODE是我设置的:

array(1) { [0]=> object(stdClass)#5 (1) 
    { 
        ["@@SESSION.sql_mode"] => string(118) "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
    }
}

但我仍然得到错误

PS。MySQL 版本是 5.7.18

4

1 回答 1

2

存储程序——过程、函数、触发器和事件——具有许多用户从未注意到的特殊机制,因为它们通常“正常工作”。

创建存储程序时,会捕获环境的某些方面并将其与代码一起存储,并在每次调用程序时使用。

SHOW CREATE PROCEDURE ...向您展示这些值。

其中之一是@@SQL_MODE

这允许过程的定义者确保在过程运行时所处的环境始终具有这些属性。

那么,官方的回答是在正确的环境中删除并重新创建程序。

但是……这里的属性实际上是存储在mysql.proc表中的。所以你有一个潜在的“快速修复”,只要你记住以下几点:

服务器操作mysql.proc表以响应创建、更改或删除存储例程的语句。不支持服务器会注意到对该表的手动操作。

https://dev.mysql.com/doc/refman/5.7/en/stored-routines-privileges.html

如果这个系统不是关键的并且你有备份,你可以小心地操作 mysql.proc 表行来改变 sql_mode,然后重新启动 MySQL 服务器进程,以便考虑到对表的更改。

请注意,另一个看似可行的选项 - 使用mysqldump并重新加载转储文件 - 将无效,因为mysqldump将语句添加到转储文件以确保使用转储时过程中存在的相同设置来恢复过程文件已创建——因此对全局服务器配置的更改将无效。

您当然可以修改转储文件以更改这些值,但这是一个有点高级的操作。

如果您从包含 SQL 语句但未显式设置 sql_mode 的文件中加载此模式,则重新加载文件也应该具有预期的效果。

最后,请注意,这ONLY_FULL_GROUP_BY是试图保护您免受以与该功能的目的不一致的方式通过扩展使用 MySQL 组的查询。从 5.7.x 开始,被拒绝的查询ONLY_FULL_GROUP_BY实际上可能会产生不确定的结果,或者可能会利用意外或巧合(而不是设计)正确的副作用或结果,并且此类行为可能在将来的版本中消失(例如,由于查询优化器的更改),因此不应依赖。

最好的解决方案是使查询在理论上是正确的。

于 2017-05-25T12:27:20.657 回答