mysql SET GLOBAL sql_mode不再起作用,并且设置在my.cnf中不存在

juzqafwq  于 2022-11-28  发布在  Mysql
关注(0)|答案(1)|浏览(716)

我正在BlueHost VPS上运行MySQL 14.14 Distrib 5.7.40 for Linux(x86_64)。几个月前,我可以成功运行以下命令:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

我必须每隔几个月重新运行一次,以避免出现此错误:

...this is incompatible with sql_mode=only_full_group_by

今天我运行时,它似乎成功,但SQL错误仍然在我的Web应用程序:
无效的查询:ORDER BY子句的表达式#1不在GROUP BY子句中,并且包含非聚合列“MyDatabase.s.EventDate”,该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode=only_full_group_by不兼容
我的完整查询即中断:

SELECT g.GroupID,
       g.GroupName,
       count(s.EventDate) AS Total
FROM Groups g
LEFT JOIN Schedule s ON g.GroupID = s.GroupID
JOIN Settings se ON g.GroupID = se.GroupID
WHERE g.OrganizationID = 479
AND g.IsActive = 1
AND IFNULL(g.IsDeleted, 0) = 0
AND IFNULL(g.IsHidden, 0) = 0
AND se.SettingName = 'HideGroupNoGames'
AND (s.EventDate > DATE_ADD(NOW(), INTERVAL 0 HOUR)
    OR g.CreateDate > DATE_ADD(DATE_ADD(NOW(), INTERVAL -1 DAY), INTERVAL 0 HOUR)
    OR se.SettingValue = 'False')
GROUP BY g.GroupID, g.GroupName
ORDER BY s.EventDate, g.GroupName

当我运行SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));时,错误并没有消失。
我尝试从终端停止和启动mysqld服务。成功,但仍然存在SQL错误。
当我运行这个程序时:select @@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

即使我已经运行了这个:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
...还有这个:

SET GLOBAL 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语句,这样错误就消失了,但我不知道怎么做。每当我调整它,我得到不同的和不正确的结果。
我从this SO post了解到SET GLOBAL是临时的,当mysql重新启动时会重置。

[mysqld]
performance-schema=0

default-storage-engine=MyISAM
interactive_timeout=300
key_cache_block_size=4096
max_heap_table_size=32M
max_join_size=1000000000
max_allowed_packet=268435456
open_files_limit=40000
query_cache_size=32M
thread_cache_size=100
tmp_table_size=32M
wait_timeout=7800
max_user_connections=50
myisam_recover_options=FORCE
innodb_file_per_table=1
innodb_flush_log_at_trx_commit=0
innodb_purge_threads=1
innodb_support_xa=0
innodb_thread_concurrency=8
pid-file=/var/lib/mysql/mysqld.pid
innodb_buffer_pool_size=55574528

我认为以下任何一种解决方案都可能对我有效:

  • 为什么SET GLOBAL sql_mode不再工作了,我如何才能使它工作呢?
  • 为什么my.cnf不包含任何关于sql_mode的内容?
  • 如何修复查询,使SQL模式无关紧要,并且不会出错?
uqzxnwby

uqzxnwby1#

好吧,有几件事正在发生。

  • 使用SET GLOBAL不会影响您执行该陈述式的目前工作阶段。它会变更全域选项,但目前工作阶段仍会使用工作阶段启动时从全域值复制的工作阶段值。如果您在使用SET GLOBAL之后启动新的工作阶段,它会继承变更。
  • 您可以使用SET SESSION sql_mode=...SET sql_mode=...(等效)更改当前会话的配置。
  • 重新启动mysqld会丢弃使用SET GLOBAL所做的任何更改,并恢复到my.cnf中的选项(或者,如果my.cnf中没有指定选项,则恢复到编译到mysqld可执行文件中的默认值)。

在MySQL 8.0中,您可以使用SET PERSIST来更改全局值,并将其写入文件,以便在重新启动mysqld时它仍然有效。请阅读更多详细信息:https://dev.mysql.com/doc/refman/8.0/en/set-variable.html
这两件事多年来一直是这样,很可能它的工作方式和文献记载的完全一样。
建议您不要更改sql模式。可以更改查询以符合默认sql模式。
由于EventDate不是GROUP BY子句中的列,因此每组可能有多个值。因此,如果使用ORDER BY s.EventDate, ...,会发生什么情况是未定义的。它应该使用组中的哪个值来排序?
您应该依群组中的 specific 值排序来解决此问题。例如,下列选项是可接受的:

ORDER BY MAX(s.EventDate), g.GroupName

ORDER BY MIN(s.EventDate), g.GroupName

相关问题