mysql子查询中的字段名称区分大小写(版本5.6与版本8)

时间:2019-07-11 07:19:35

标签: mysql sql mysql-5.6 mysql-8.0

从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     |
+---------------+

1 个答案:

答案 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的拼写。尽管作为免责声明,但该行为仍未指定,因此极端情况或将来的版本可能仍会表现不同。