PL/SQL 循环“返回”记录

Posted

技术标签:

【中文标题】PL/SQL 循环“返回”记录【英文标题】:PL/SQL looping 'back' through the records 【发布时间】:2020-03-31 16:25:24 【问题描述】:

我有一个问题希望你能帮忙解决。

我有一个名为 PRODUCT 的表:

Product_ID               NOT NULL NUMBER(10)       
TARGET_PRODUCT                    VARCHAR2(10)  
SOURCE_PRODUCT                    VARCHAR2(10)  

所以每个 target_product 都由 source_product 组成(第一个除外 - 第一个只有 target_product 并且 source_product 为空) 我需要为给定的 target_product 找到第一个 source_product。 我需要循环“返回”,直到源产品为空。 这种情况有解决方案吗?

提前致谢

【问题讨论】:

请分享示例数据并通过所需的输出解释问题,以便具体回答您的问题。 【参考方案1】:

你需要的不是循环,而是分层查询。查看以下基于 Scott 的 EMP 表的示例。

这是它的内容;员工分层显示,显示谁是谁的老板:

SQL> select level,
  2         lpad(' ', level * 2, ' ') || e.ename name
  3  from emp e
  4  start with e.mgr is null
  5  connect by prior e.empno= e.mgr;

     LEVEL NAME
---------- ---------------
         1   KING
         2     JONES
         3       SCOTT
         4         ADAMS
         3       FORD
         4         SMITH
         2     BLAKE
         3       ALLEN
         3       WARD
         3       MARTIN
         3       TURNER
         3       JAMES
         2     CLARK
         3       MILLER

14 rows selected.

SQL>

当你想从表格的中间开始(例如,从SMITH开始),你可以“反转”它:

SQL> select level lvl,
  2            lpad(' ', level * 2, ' ') || e.ename name
  3     from emp e
  4     start with e.ename = 'SMITH'
  5     connect by prior e.mgr= e.empno;

       LVL NAME
---------- ---------------
         1   SMITH
         2     FORD
         3       JONES
         4         KING

SQL>

最后,将该查询用作 CTE(或子查询,如果您的 Forms 版本不支持 CTE),获取名称具有***别的查询:

SQL> with temp as
  2    (select level lvl,
  3            lpad(' ', level * 2, ' ') || e.ename name
  4     from emp e
  5     start with e.ename = 'SMITH'
  6     connect by prior e.mgr= e.empno
  7    )
  8  select trim(t.name) name
  9  from temp t
 10  where t.lvl = (select max(t1.lvl) from temp t1);

NAME
---------------
KING

SQL>

或者,更好的是,使用connect_by_isleaf

SQL> select e.ename name
  2  from emp e
  3  where connect_by_isleaf = 1
  4  start with e.ename = 'SMITH'
  5  connect by prior e.mgr= e.empno;

NAME
---------------
KING

SQL>

【讨论】:

【参考方案2】:

您可以试试这个,它将返回给定 target_product 的基本 target_product:

select * from (
  select PRODUCT_ID, TARGET_PRODUCT, SOURCE_PRODUCT 
  from PRODUCT
  start with target_product = '<your target product>'
  connect by prior SOURCE_PRODUCT = TARGET_PRODUCT
)
where SOURCE_PRODUCT is null;

【讨论】:

以上是关于PL/SQL 循环“返回”记录的主要内容,如果未能解决你的问题,请参考以下文章

在 PL/SQL 中附加来自每个循环迭代的多条记录

PL/SQL 在 for 循环中执行即时异常处理

PL/SQL UTL_FILE:循环如何自动返回下一行?

PL/SQL 在过程中返回记录

调用从 Hibernate 返回记录列表的 PL/SQL 函数

oracle 11g 中 for 循环中的 PL/SQL 限制