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

修正された PL/SQL 構文を使用したメソッドは、次のようになります。

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;

ただし、おそらく次のような 1 つのステートメントですべてを取得できます。

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;

階層クエリに関する Oracle ドキュメントを参照してください

于 2013-01-07T17:49:13.083 に答える
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;

もう 1 つの優れたオプション (プライマリ) は、CONNECT BY, START WITH です。

于 2015-10-15T12:20:59.937 に答える
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 に答える