使用SQL查询或函数以递归方式跟踪合并

时间:2018-11-16 11:19:04

标签: sql oracle plsql recursive-query

我有两个表:

throw

我想编写一个查询或函数,该查询或函数将获取person_id的列表,并将它们映射到最终合并到的任何人(如果有)。如果有周期性合并,我也想抛出一个错误。

try/catch

我怎样才能做到这一点?使用CTE,CONNECT BY还是递归功能?

1 个答案:

答案 0 :(得分:0)

这是一个搜索姓氏列表的功能

public class ConditionalOrderService{

public void doMapping(){

IConditionalOrder order = new ConditionalOrderDTO();

ModelMapper mapper= new ModelMapper();
mapper.map(order,OrderDestination.class); 
}
}

这是一个调用列表的示例,该列表不会发生异常

CREATE OR REPLACE FUNCTION findTheLastPersonList(
   pi_startPersonList sys.odcinumberlist
)
RETURN sys.odcinumberlist
AS
  lv_lastPersonList sys.odcinumberlist := new sys.odcinumberlist();

  /* Get the last merged person in a chain
   *
   * @param pi_startPersonId  Person from which searching should be started
   * @return                  Id of the last person in a chain or  pi_startPersonId in case person is merged to nobody
   */   
  FUNCTION findTheLastPerson(
      pi_startPersonId NUMBER
  )
  RETURN NUMBER
  AS
    lv_laslPersonId NUMBER;
  BEGIN

    BEGIN
      WITH t1(person_id, person_merged_to_id, lvl) AS (
        -- Anchor member.
        SELECT person_id,
               person_merged_to_id,
               1 AS lvl
          FROM person_merge
         WHERE person_id = pi_startPersonId
         UNION ALL
        -- Recursive member.
        SELECT t2.person_id,
               t2.person_merged_to_id,
               lvl+1
          FROM person_merge t2, t1
         WHERE t2.person_id = t1.person_merged_to_id
      )
      SELECT person_merged_to_id
        INTO lv_laslPersonId
        FROM (
              SELECT person_id,
                     person_merged_to_id,
                     lvl,
                     max(lvl) OVER () AS max_lvl
              FROM   t1
             ) t
       WHERE t.lvl = t.max_lvl;
     EXCEPTION
       WHEN NO_DATA_FOUND THEN
         lv_laslPersonId := pi_startPersonId;
     END;

     RETURN lv_laslPersonId;

  END findTheLastPerson;

BEGIN
  FOR i IN 1..pi_startPersonList.Count LOOP
    lv_lastPersonList.Extend();
    lv_lastPersonList(i) := findTheLastPerson(pi_startPersonId => pi_startPersonList(i));
  END LOOP;
  RETURN lv_lastPersonList;
END findTheLastPersonList;

以及引发异常的情况下的通话示例

DECLARE
  lv_toFind sys.odcinumberlist := sys.odcinumberlist(1, 2, 3, 4);
  lv_result sys.odcinumberlist;
BEGIN
  lv_result := findTheLastPersonList(
                   pi_startPersonList => lv_toFind
               );

  FOR i IN 1..lv_result.COUNT LOOP
    dbms_output.put_line(lv_toFind(i) || ' => ' || lv_result(i));
  END LOOP;
END;
/