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 mysql 和 mysql --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”