相同的查询和数据结构,但MySQL 8返回的结果与MySQL 5不同?

Same query and data structure, but MySQL 8 returns different result with MySQL 5?(相同的查询和数据结构,但MySQL 8返回的结果与MySQL 5不同?)
本文介绍了相同的查询和数据结构,但MySQL 8返回的结果与MySQL 5不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将数据库从AWS Aurora 1.22.3(与MySQL 5.6兼容)迁移到MySQL 8,并有一个查询返回帐户及其父帐户(如果是父帐户,则返回子帐户)。

帐户表将包含:

Account_id(主键)、Parent_Account_id(外键) 帐户名,...

例如,我的帐户520具有父帐户519:

account_id,tenant_id,parent_account_id,account_name,account_code,account_class,account_type,account_description,status,is_master_account,currency_code,tax_type,pending_balance,authorised_balance,total_balance,related_party_id,creator_id
519,1,NULL,"SANTOS LIMITED - Trade1",000604,ASSET,FINRECEIVABLE,NULL,ACTIVE,1,AUD,BASEXC,0.000000,0.000000,0.000000,321,1
520,1,519,"SANTOS LIMITED - Trade Card1",000604-1,ASSET,FINRECEIVABLE,NULL,ACTIVE,0,AUD,BASEXC,0.000000,0.000000,0.000000,321,1

以下是我的问题:

    SELECT 
        t_all.account_id -- , parent_level, t_all.level 
    FROM ( 
        -- GET ALL CHILDREN 
        SELECT 
            account_id, 
            parent_account_id, 
            null as parent_level, 
            (@l:=@l + 1) AS level 
        FROM 
        ( 
            SELECT 
                account_id, 
                tenant_id, 
                parent_account_id 
            FROM Account 
            ORDER BY 
                parent_account_id, 
                account_id 
        ) account_sorted, 
        ( 
            SELECT @pv := 520, @l := 0, @cl := 0 
        ) initialisation 
        WHERE 
        account_id = @pv OR 
        find_in_set(parent_account_id, @pv) > 0 
        AND 
        @pv := concat(@pv, ',', account_id) 
        
        UNION 
        
        -- GET ALL PARENTS 
        SELECT 
            account_id, 
            parent_account_id, 
            level as parent_level, 
            null as level 
        FROM 
        ( 
            SELECT 
                _id AS account_id, 
                parent_account_id, 
                @cl := @cl + 1 AS level 
            FROM 
            ( 
                SELECT 
                    @r AS _id, 
                    ( 
                        SELECT @r := parent_account_id 
                        FROM Account 
                        WHERE account_id = @r 
                    ) AS parent_account_id, 
                    @l := @l + 1 AS level 
                FROM 
                ( 
                    SELECT @r := 520, @l := 0, @cl := 0 
                ) vars, 
                Account h 
                WHERE 
                    @r <> 0 
                ORDER BY level DESC 
            ) qi 
        ) qo 
    ) as t_all 
    order by level desc , parent_level asc; 

旧版本(MySQL5)将返回3条记录(520,519,520),而MySQL8只返回一个帐户id 520。预期输出将与旧版本相同。

您认为是什么原因导致此问题?迁移数据库版本时应如何确保查询结果一致?

非常感谢您的帮助。

推荐答案

出现这种行为的一般原因是mySQL使用了一些与您使用的变量不兼容的优化。您使用了相当多的变量,所以我不想在这里找出哪些优化对您有特别的影响,但请参见Myanswer here作为一个例子。通常,如果变量的值发生变化,MySQL会对您的子查询做出一些不一定正确的假设。

一般的解决方案是阻止MySQL进行这些优化,目前,这些优化可以普遍通过物化来完成。您可以通过向所有子查询添加任意大限制来实现这一点,例如

... FROM Account 
ORDER BY parent_account_id, account_id 
LIMIT 100000000 -- add this
...

... FROM Account WHERE account_id = @r 
LIMIT 100000000 -- add this
...

这样做的效果是,MySQL将实际生成查询的所有行,并随后(可能)以您希望的方式计算变量,因此您应该会得到预期的结果。(如果你没有,你可能忘记了一些限制,所以试着把它添加到更多的地方)。

一般说来,尽管变量的使用通常和实际上都像预期的那样工作,但在MySQL8之前,变量的使用就已经正式变得脆弱了,例如,参见documentation

对于其他语句,例如SELECT,您可能会得到预期的结果,但这并不能保证。在下面的语句中,您可能认为MySQL首先计算@a,然后再进行赋值:

 SELECT @a, @a:=@a+1, ...;

但是,涉及用户变量的表达式的计算顺序未定义

还有一个更一般的警告:您使用变量的方式从MySQL8开始就不再推荐使用,并且可能会在MySQL的某些未来版本中导致语法错误。您可能希望查看(recursive) Common Table Expressions和How to create a MySQL hierarchical recursive query?中的一些指针,了解如何在不使用变量的情况下重写查询。

这篇关于相同的查询和数据结构,但MySQL 8返回的结果与MySQL 5不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Execute complex raw SQL query in EF6(在EF6中执行复杂的原始SQL查询)
Hibernate reactive No Vert.x context active in aws rds(AWS RDS中的休眠反应性非Vert.x上下文处于活动状态)
Bulk insert with mysql2 and NodeJs throws 500(使用mysql2和NodeJS的大容量插入抛出500)
Flask + PyMySQL giving error no attribute #39;settimeout#39;(FlASK+PyMySQL给出错误,没有属性#39;setTimeout#39;)
auto_increment column for a group of rows?(一组行的AUTO_INCREMENT列?)
Sort by ID DESC(按ID代码排序)