SQL_MODE无法在MySQL 5.7.18

时间:2017-05-24 22:20:21

标签: php mysql ubuntu apache2 sql-mode

我从PHP应用程序中收到以下错误:

  

错误的SQL查询(数据库)在没有GROUP BY的聚合查询中,SELECT列表的表达式#1包含非聚合列< db_20172201.cm_order.buyer&#39 ;;这与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

1 个答案:

答案 0 :(得分:1)

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

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

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拒绝的查询实际上可能产生非确定性结果,或者可能利用偶然或巧合的副作用或结果 - 而不是设计 - - 并且此类行为可能会在将来的版本中消失(例如,由于查询优化器中的更改),因此不应该依赖它。

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