0

我试图弄清楚如何通过层次结构循环,我不知道如何放入 PLSQL。我想要实现的目标:我想知道在层次结构中比我高 10 级的是哪个部门:

假设我有一张桌子,上面有一个部门和一个父部门。我想执行这种操作:

select my_department from table_departments as v_department
FOR counter in 1...9
LOOP
v_department:=
(SELECT parent_department
FROM table_department_hierarchy
WHERE child_department=v_department)
END LOOP as top_department;

我无法弄清楚正确的语法,有没有勇敢的灵魂可以帮助我?

4

3 回答 3

2

Your method with corrected PL/SQL syntax would be something like:

begin
  select my_department into v_department from table_departments;
  FOR counter in 1...9
  LOOP
    SELECT parent_department
    INTO v_department
    FROM table_department_hierarchy
    WHERE child_department=v_department;
  END LOOP:
END;

However you could perhaps get it all in one statement something like this:

SELECT parent_department
INTO v_department
FROM
( SELECT parent_department, level as lvl
  FROM table_department_hierarchy
  CONNECT BY child_department = PRIOR parent_department
  START WITH child_department = v_department
)
WHERE lvl = 9;

See Oracle docs on hierarchical queries

于 2013-01-07T17:49:13.083 回答
0

这是我很久以前编写的一个大型 pl/sql 程序,旨在遍历员工/老板报告树一直到顶部(CEO)。这个版本是 Peoplesoft 特有的,但只要您阅读的内容在记录中具有父/子关系,它就可以处理任何事情......我还有其他更动态的版本,但这可能是最容易破译的。我删除了一些你不会关心的绒毛东西。此外,由于报告工具可以使用它,因此该特定解决方案会出于许多不同原因将其交付给表格...

此外,它动态确定级别,因此您不必像使用连接解决方​​案那样知道有多少级别。

希望能帮助到你:

CREATE OR REPLACE PROCEDURE DW."SPW_T_RESOURCE_HIERARCHY" (iCommit   In Integer Default 1000,
                                                     pdBegin   In Date Default trunc(Sysdate) - 3,
                                                     pdEnd     In Date Default trunc(Sysdate) + 1,
                                                     vTruncate In Varchar2 Default 'Y' ) Is

   ------------------------------------------------------
   --  DECLARATIONS
   ------------------------------------------------------

   Cursor curDataSource Is

   ---**********************************----
   ---****BEGIN CUSTOMIZE THIS BLOCK****----
   ---**********************************----
      Select
                Eh.empl_id         F_DESCENDANT_ID
               ,Eh.Super_Empl_Id   F_IMMEDIATE_ANCESTOR_ID
        From
               Employee_Header EH
       Where
               EH.SUPER_EMPL_ID IS NOT NULL OR EH.TERM_DATE IS NULL;

   ---**********************************----
   ---****END CUSTOMIZE THIS BLOCK******----
   ---**********************************----

   dNow              Date := Sysdate;
   iTotalRows        Integer := 0;
   iTotalErrors      Integer := 0;

   ---**********************************----
   ---****BEGIN CUSTOMIZE THIS BLOCK****----
   ---**********************************----
   vDescendentID     Varchar2(20);
   iDescendentLevel  Integer := 1;
   iAncestorLevel    Integer := 0;
   vAncestorID       Varchar2(20);
   vTmpAncestorID    Varchar2(20);
   vTmpEmployeeID    Varchar2(20);

   ---**********************************----
   ---****END CUSTOMIZE THIS BLOCK******----
   ---**********************************----

   ------------------------------------------------------
   -- END DECLARATIONS
   ------------------------------------------------------

   ------------------------------------------------------
   -- BEGIN MAIN
   ------------------------------------------------------
Begin
   -- Loop over source records
   For recDataSource In curDataSource
   Loop
      iDescendentLevel := 1;
      vAncestorID := recDataSource.f_Immediate_Ancestor_Id;

      -- Start Transaction
      Begin
         while (Trim(vAncestorID) is not null)
         loop
             Begin
                          -- Fetch Next Ancestor
                 Select EH.SUPER_EMPL_ID
                   Into vTmpAncestorID
                   From
                        EMPLOYEE_HEADER EH
                  Where
                        EH.EMPL_ID = vAncestorID;
             Exception
             When Others Then
                vTmpAncestorID := null;
             End;

              If NVL(vTmpAncestorID,'-XYZ-') = NVL(vAncestorID,'-123-') Then
                 vTmpAncestorID := null;
              End If;

              vAncestorID := vTmpAncestorID;
              iDescendentLevel := iDescendentLevel + 1;
         end loop;

         -- Insert Resource Base
         Insert Into T_RESOURCE_HIERARCHY
            (
                T_RESOURCE_HIERARCHY.F_HIERARCHY_NAME,
                T_RESOURCE_HIERARCHY.F_DESCENDANT_LEVEL,
                T_RESOURCE_HIERARCHY.F_DESCENDANT_ID,
                T_RESOURCE_HIERARCHY.F_ANCESTOR_LEVEL,
                T_RESOURCE_HIERARCHY.F_ANCESTOR_ID
            )
         Values
            (
                'Physical Org Chart',
                iDescendentLevel,
                recDataSource.f_Descendant_Id,
                To_Number(Decode(iDescendentLevel,1,2,iDescendentLevel) - 1),
                NVL(recDataSource.f_Immediate_Ancestor_Id,'ROOT')
            );


      -- Insert MySelf Into Resource Base as well for full hierarchy research
         Insert Into T_RESOURCE_HIERARCHY
            (
                T_RESOURCE_HIERARCHY.F_HIERARCHY_NAME,
                T_RESOURCE_HIERARCHY.F_DESCENDANT_LEVEL,
                T_RESOURCE_HIERARCHY.F_DESCENDANT_ID,
                T_RESOURCE_HIERARCHY.F_ANCESTOR_LEVEL,
                T_RESOURCE_HIERARCHY.F_ANCESTOR_ID
            )
         Values
            (
                'Physical Org Chart',
                iDescendentLevel,
                recDataSource.f_Descendant_Id,
                iDescendentLevel,
                NVL(recDataSource.f_Descendant_Id,'ROOT')
            );

      -- Now Its Time To Climb The Tree
      -- For This Employee
         vAncestorID := recDataSource.f_Immediate_Ancestor_Id;
         iAncestorLevel := iDescendentLevel-1;
         vTmpAncestorID := null;

         -- Loop over parents
         while (Trim(vAncestorID) is not null)
         loop

             Begin
                 -- Fetch Next Ancestor
                 Select EH.SUPER_EMPL_ID
                   Into vTmpAncestorID
                   From
                        EMPLOYEE_HEADER EH
                  Where
                        EH.EMPL_ID = vAncestorID;
             Exception
             When Others Then
                vTmpAncestorID := null;
             End;

             If NVL(vTmpAncestorID,'-XYZ-') = '-XYZ-' Then
                 vTmpAncestorID := null;
             End If;

              vAncestorID := vTmpAncestorID;
              iAncestorLevel := iAncestorLevel - 1;

             If vAncestorID is not null Then
                 -- Insert Resource Base
                 Insert Into T_RESOURCE_HIERARCHY
                    (
                        T_RESOURCE_HIERARCHY.F_HIERARCHY_NAME,
                        T_RESOURCE_HIERARCHY.F_DESCENDANT_LEVEL,
                        T_RESOURCE_HIERARCHY.F_DESCENDANT_ID,
                        T_RESOURCE_HIERARCHY.F_ANCESTOR_LEVEL,
                        T_RESOURCE_HIERARCHY.F_ANCESTOR_ID
                    )
                 Values
                    (
                       'Physical Org Chart',
                        iDescendentLevel,
                        recDataSource.f_Descendant_Id,
                        iAncestorLevel,
                        vAncestorID

                    );
             End If;
         end loop;


         -- TRANSACTION EXCEPTION HANDLING
      Exception
         When Others Then

      End;

      -- ASSIGN HOW MANY RECORDS PROCESSED
      iTotalRows := curDataSource%Rowcount;

      -- CONDITIONAL/INCREMENTAL TRANSACTION COMMIT
      If Mod(iTotalRows, iCommit) = 0
      Then
         Commit;
      End If;

   End Loop;


   -- FINAL COMMIT AND MD UPDATE
   Commit;


   -- MAIN EXCEPTION HANDLING
Exception
   When Others Then
      Begin
         iExceptionCode    := Sqlcode;
         vExceptionMessage := Sqlerrm;
         Raise_application_error(Sqlcode, Sqlerrm);
      End;

   ------------------------------------------------------
   -- END MAIN
   ------------------------------------------------------
End SPW_T_RESOURCE_HIERARCHY;
/
于 2013-01-07T19:45:40.400 回答
0

请检查以下示例。未经测试,但相信:)

DECLARE
G_EMPLOYEE_ID NUMBER:=1880;
FUNCTION GET_MANAGER(V_EMPLOYEE_ID NUMBER) RETURN NUMBER IS 
V_MANAGER_ID NUMBER;
BEGIN
  SELECT ID_MANAGER INTO V_MANAGER_ID FROM EMPLOYEES WHERE EMPLOYEE_ID = V_EMPLOYEE_ID;
  RETURN V_MANAGER_ID;
EXCEPTION
  WHEN OTHERS THEN
  RETURN NULL;
END;
BEGIN
LOOP 
DBMS_OUTPUT.PUT_LINE('EMPLOYEE:' || G_EMPLOYEE_ID);
G_EMPLOYEE_ID := GET_MANAGER(G_EMPLOYEE_ID);
DBMS_OUTPUT.PUT_LINE('MANAGER:' || G_EMPLOYEE_ID);
EXIT WHEN G_EMPLOYEE_ID IS NULL;
END LOOP;
END;

另一个不错的选择(主要)是 CONNECT BY, START WITH

于 2015-10-15T12:20:59.937 回答