MySQL 8 不检测选择不同查询中的功能依赖关系

Posted

技术标签:

【中文标题】MySQL 8 不检测选择不同查询中的功能依赖关系【英文标题】:MySQL 8 does not detect functional dependencies in select distinct queries 【发布时间】:2019-02-13 23:37:10 【问题描述】:

我使用这个查询创建了一个表:

create table a (
  `id` int not null auto_increment,
  b varchar(10),
  primary key (`id`)
);

执行

select distinct `id` from a order by `b`;

导致此错误:

ERROR 3065 (HY000): ORDER BY 子句的表达式#1 不在 SELECT 列表中,引用列 'portal.a.b' 不在 SELECT 列表中;这与 DISTINCT 不兼容

但如果我将查询更改为

select `id` from a group by `id` order by `b`;

逻辑上等价,成功了。

我正在使用 official Docker image for mysqlmysql --version 显示器

mysql Ver 8.0.12 for Linux on x86_64 (MySQL Community Server - GPL)

似乎 MySQL 仍然没有在 select distinct 查询中检测到函数依赖关系。我对吗? MySQL 的开发人员会解决这个问题吗?

【问题讨论】:

【参考方案1】:

相反的行为实际上被报告为错误和fixed in MySQL 5.7.5:

更正了与 ONLY_FULL_GROUP_BY SQL 模式相关的几个问题:

启用 ONLY_FULL_GROUP_BY 后,如果访问的表被视图替换,一些有效查询将被拒绝。

SELECT DISTINCT col1 ... ORDER BY col2 形式的查询被 SQL2003 禁止(隐藏的 ORDER BY 列与 DISTINCT 组合),但在启用 ONLY_FULL_GROUP_BY SQL 模式时未被拒绝。

另外,documentation 明确指出这是预期的行为:

为防止出现此问题,如果任何 ORDER BY 表达式至少不满足以下条件之一,则具有 DISTINCT 和 ORDER BY 的查询将被拒绝为无效:

表达式等于选择列表中的一

表达式引用并属于查询的选定表的所有列都是选择列表的元素

没有提到功能依赖。与group by相比,相关的错误信息也没有引用函数依赖。

虽然 sql 标准中的可选功能 T301 功能依赖项确实修改了group by(和其他)的一致性规则,但它不会改变任何限制order by加上distinct,表示还是禁止的。

【讨论】:

【参考方案2】:

这来自于 MySQL 5.7 引入的新 SQL 模式:ONLY_FULL_GROUP_BY

此模式的目标是使 MySQL 在 GROUP BY 查询中表现得像 SQL 标准。

此模式已在您的数据库上激活。您可以禁用它,或者调整您的查询以遵守标准,这可能是最好的做法。

这会抛出你的错误:

SET sql_mode = 'ONLY_FULL_GROUP_BY';

drop table a;
create table a (
  `id` int not null auto_increment,
  b varchar(10),
  primary key (`id`)
);
INSERT INTO a VALUES (NULL, 'aaaa');
INSERT INTO a VALUES (NULL, 'bbbb');

select distinct `id` from a order by `b`;

如果您删除 ONLY_FULL_GROUP_BY 模式,您会得到结果:

SET sql_mode = '';

drop table a;
create table a (
  `id` int not null auto_increment,
  b varchar(10),
  primary key (`id`)
);
INSERT INTO a VALUES (NULL, 'aaaa');
INSERT INTO a VALUES (NULL, 'bbbb');

select distinct `id` from a order by `b`;

你可以在Rextester上看到它的直播

【讨论】:

以上是关于MySQL 8 不检测选择不同查询中的功能依赖关系的主要内容,如果未能解决你的问题,请参考以下文章

MySQL查询为什么选择使用这个索引?——基于MySQL 8.0.22索引成本计算

MySQL查询为什么选择使用这个索引?——基于MySQL 8.0.22索引成本计算

MySQL查询为什么选择使用这个索引?——基于MySQL 8.0.22索引成本计算

创建React App需要一个依赖关系。"babel-loader": “8.1.0”

Visual Studio 2013 中的 MSM 合并模块:未检测到依赖关系

mysql依赖安装问题