PL/SQL 中的嵌套游标和递归

Nested Cursor & Recursion in PL/SQL

我是 PL/SQL 的新手,刚开始使用游标。我正在编写一个小程序来打印员工的递归跟踪 - >主管一直到大老板。本质上,我的查询将输出 employee、supervisor1,然后输出 supervisor1、supervisor2,一直到 supervisorn,null。我的目标是编写一个简短的 PL/SQL 程序,为每个员工重复执行此过程。我的代码如下:

set serveroutput on;

DECLARE
    v_iteration number := 0;

BEGIN
    for x in (select * from e)
    loop
        dbms_output.put_line('recursive trace #' || v_iteration);
        v_iteration := v_iteration + 1;
        for y in 
            (WITH sup_hierarch (employee, supervisor) AS
            (select x.ssn, x.superssn FROM e
            UNION ALL
            select supervisor, superssn
            from sup_hierarch join e on sup_hierarch.supervisor = e.ssn
            where sup_hierarch.supervisor is not null)
            select * from sup_hierarch)


        loop
            dbms_output.put_line(y.employee || ', ' || y.supervisor);
        end loop;


    end loop;
END;
/

我使用了两个隐式游标,外层隐式游标用于遍历员工table(为了打印每个员工的递归跟踪),内层隐式游标用于遍历递归跟踪本身。代码有点工作,示例输出:

recursive trace #6
666884444, 333445555
666884444, 333445555
666884444, 333445555
666884444, 333445555
666884444, 333445555
666884444, 333445555
666884444, 333445555
666884444, 333445555
333445555, 888665555
333445555, 888665555
333445555, 888665555
333445555, 888665555
333445555, 888665555
333445555, 888665555
333445555, 888665555
333445555, 888665555
888665555,
888665555,
888665555,
888665555,
888665555,
888665555,
888665555,
888665555,

根据我的全部输出,每个员工的循环工作正常。此外,每个员工的递归跟踪都正常工作(也就是说,每个员工都有正确的递归深度和堆栈)。但是,递归跟踪中的每一行都打印了 number_of_employee 次,而我希望它打印一次。这是为什么?

您的代码的问题是您的 WITH 子句的第一部分:它 returns 与 'e' 中一样多的行具有相同的日期。 为什么不这样做呢:

    DECLARE
        v_iteration number := 0; -- useless in the version

    BEGIN
        for y in 
                (WITH sup_hierarch (employee, supervisor) AS
                (select x.ssn, x.superssn FROM e
                UNION ALL
                select supervisor, superssn
                from sup_hierarch join e on sup_hierarch.supervisor = e.ssn
                where sup_hierarch.supervisor is not null)
                select * from sup_hierarch)
        loop
            dbms_output.put_line(y.employee || ', ' || y.supervisor);
        end loop;

    END;
    /

如果你想要 2 个循环,只是为了得到你的迭代:

    DECLARE
        v_iteration number := 0;

    BEGIN
        for x in (select * from e)
        loop
            dbms_output.put_line('recursive trace #' || v_iteration);
            v_iteration := v_iteration + 1;
            for y in 
                (WITH sup_hierarch (employee, supervisor) AS
                (select x.ssn, x.superssn FROM dual
                UNION ALL
                select supervisor, superssn
                from sup_hierarch join e on sup_hierarch.supervisor = e.ssn
                where sup_hierarch.supervisor is not null)
                select * from sup_hierarch)


            loop
                dbms_output.put_line(y.employee || ', ' || y.supervisor);
            end loop;


        end loop;
    END;
    /