Trying to recursively select rows based on prior row parent in SQL

后端 未结 1 1048
我在风中等你
我在风中等你 2021-01-26 17:12

Using the table ROLE(ROLE_ID, PARENT_ROLE_ID) how can I get all rows that are dependent on another? For example, a root level role will have a null value for [PARENT_ROLE_ID],

相关标签:
1条回答
  • 2021-01-26 17:43
    -- drop table role;
    create table role
    (   id int not null auto_increment primary key, -- for kicks and if i screw up
        roleId int not null,    -- i will manually provide it so i can see it
        parent int null,
        unique index (roleId)
    );
    
    insert role(roleId,parent) values (1,null),(2,null),(3,2),(4,3),(5,3),(6,3),(7,4),(8,3),(9,6),(10,6),(11,10);
    
    -- if i want to delete roleId A then i need to delete anything with a parent=A (B) and all of B's lineage too
    
    -- drop procedure deleteParentDownwards;
    delimiter $$
    create procedure deleteParentDownwards
    (
    deleteMe int
    )
    BEGIN
        -- deleteMe parameter means i am anywhere in hierarchy of role
        -- and i want me and all my offspring deleted (no orphaning of children or theirs)
        declare bDoneYet boolean default false;
        declare working_on int;
        declare theCount int;
    
        CREATE TABLE xxDeleteRoleHierarchyxx
        (
            roleId int not null,
            processed int not null
        );
    
        set bDoneYet=false;
        insert into xxDeleteRoleHierarchyxx (roleId,processed) select deleteMe,0;
        while (!bDoneYet) do
            select count(*) into theCount from xxDeleteRoleHierarchyxx where processed=0;
    
            if (theCount=0) then 
                -- found em all
                set bDoneYet=true;
            else
                -- one not processed yet, insert its children for processing
                SELECT roleId INTO working_on FROM xxDeleteRoleHierarchyxx where processed=0 limit 1;
                insert into xxDeleteRoleHierarchyxx (roleId,processed)
                select roleId,0 from role
                where parent=working_on;
    
                -- mark the one we "processed for children" as processed
                update xxDeleteRoleHierarchyxx set processed=1 where roleId=working_on;
            end if;
        end while;
        delete from role where roleId in (select roleId from xxDeleteRoleHierarchyxx);
        drop table xxDeleteRoleHierarchyxx;
    END
    $$
    
    call deleteParentDownwards(3); -- deletes many
    
    call deleteParentDownwards(6); -- deletes 4 (assuming line above was not called first!)
    
    0 讨论(0)
提交回复
热议问题