从MySQL5.6升级到MySQL8在子查询中造成字段名称区分大小写的问题。
我尝试阅读MySQL8文档和各种与区分大小写有关的文章,但找不到解决方案。
SELECT productId
FROM ( SELECT a.PRODUCTID
FROM ( SELECT ProdId ProductId
FROM tblproductmaster
ORDER BY CreatedDateTime DESC limit 10 ) a ) a ;
版本5.6和版本8的预期输出
+-----------------+
| productId |
+-----------------+
| PROJTZ00734 |
| 75882M56R00B4 |
| 1161085S10-B200 |
| HRZ00136 |
| HRZ00135 |
| HRZ00134 |
| HRZ00133 |
| IMPOZ00148 |
| IMPOZ00147 |
| MAINZ01682 |
+-----------------+
但是5.6版的实际输出是
+-----------------+
| productId |
+-----------------+
| PROJTZ00734 |
| 75882M56R00B4 |
| 1161085S10-B200 |
| HRZ00136 |
| HRZ00135 |
| HRZ00134 |
| HRZ00133 |
| IMPOZ00148 |
| IMPOZ00147 |
| MAINZ01682 |
+-----------------+
,在版本8中是
+---------------+
| PRODUCTID |
+---------------+
| 46201M79G00B3 |
| 46201M59K00B2 |
| 59288M81R10 |
| 59238M81R00 |
| 59286M81R10 |
| 59236M81R00 |
| 59234M81R00 |
| MAINZ01482 |
| MAINZ01481 |
| CONZ00171 |
+---------------+
答案 0 :(得分:0)
列名是case insensitive by definition:
列,索引,存储的例程和事件名称在任何平台上都不区分大小写,列别名也不区分大小写。
MySQL可以自由选择任何版本,但是会选择它附带的最新版本。不一定是您认为的版本。
这里发生的是MySQL 8中的优化器通过merging the two outer layers into one优化了查询,而MySQL 5.6尚不知道这种优化。 MySQL 5.6中的执行计划。应该看起来类似于
id select_type table type possible_keys ...
1 PRIMARY <derived2> ALL
2 DERIVED <derived3> ALL
3 DERIVED tblproductmaster ALL
对于MySQL 5.7和更高版本,您应该少一行:
id select_type table type possible_keys ...
1 PRIMARY <derived3> ALL
3 DERIVED tblproductmaster ALL
这显然是一个好主意,因为它可以减少工作量,从而使查询运行速度更快。基本上,MySQL将您的查询简化为类似
SELECT a.PRODUCTID from (SELECT ProdId ProductId FROM tblproductmaster
ORDER BY CreatedDateTime DESC limit 10 ) a
没有规范要求MySQL在合并过程中选择外部拼写或内部拼写(将来的版本中可能会更改)。但是,MySQL将使用别名,如果需要特定的情况,将在此处使用别名:
SELECT productId as productId FROM ( SELECT a.PRODUCTID from ( ... ) a ) a
应该屈服
+-----------------+
| productId |
+-----------------+
| PROJTZ00734 |
不幸的是,您将需要为此修改(所有)查询,没有“总是选择最强的拼写大小写”选项,对于MySQL,大小写是不相关的,并且从未指定,仅通过偶然的机会证明MySQL到现在为止都选择了您喜欢的情况。
但是,您可以完全禁用此合并优化。尽管它会使某些查询变慢,但它可能是一个临时解决方案,可以使您的代码正常工作,直到您熟练使用它为止(最终应这样做)。要禁用derived_merge
(并保留所有其他选项的默认设置),可以使用optimizer switch
set global optimizer_switch='derived_merge=off';
请不要忘记将其添加到您的配置文件中,否则它将无法在服务器重新启动后幸免。就合并而言,这应该使您的查询的行为类似于MySQL 5.6,并且副作用是,您应该获得MySQL 5.6的拼写。尽管作为免责声明,但该行为仍未指定,因此极端情况或将来的版本可能仍会表现不同。