嵌套 PL/SQL 游标和 For 循环工作正常,但 "Connecting to the database xxx"

Nested PL/SQL cursors and For loop work OK but "Connecting to the database xxx"

简介:

我是 PL/SQL 11g Express 的初学者。所以大佬们手下留情。。这个程序有两个游标嵌套一个for循环,希望根据出现次数复制订单行,以便进一步处理。

例如如果订单号> 2,则复制整行并将交易金额除以交易金额的编号。

原始数据: Table:D_MP

BARCODE   Product    Amount         ID      Num
76Q7Q7    Water      10.00       20160601    2
8JJ1NK    Apple       5.50       20160601    1
8JJ1YK    Orange      4.50       20160608    1
8JJ1CK    Banana      4.00       20160608    2

结果: Table:D_MP_1

  BARCODE   Product    Amount         ID      Num
    76Q7Q7    Water       5.00       20160601    1
    76Q7Q7    Water       5.00       20160601    1
    8JJ1NK    Apple       5.50       20160601    1
    8JJ1YK    Orange      4.50       20160608    1
    8JJ1CK    Banana      2.00       20160608    1
    8JJ1CK    Banana      2.00       20160608    1

问题:

这个过程的输出看起来没问题,但每次我 运行 它,SQL 开发人员的日志一直在 "Connecting to the database xxx",没有显示与数据库 xxx 断开连接,并且我必须自己停止程序。由于我只有 10 多行原始数据用于测试目的,我想知道是什么阻止了它 disconnecting/stopping.


这是代码

Create or replace PROCEDURE MULTIPLE_CURSORS_TEST is
   pac_row D_MP%ROWTYPE;
   v_barcode D_MP.BARCODE%TYPE;
   v_Num D_MP.Num%TYPE;
   v_Amount D_MP.Amount%TYPE;
CURSOR mul_pa_LOOP_CURSOR
  IS
  Select *
  from D_MP;

CURSOR mul_pa_ID_CURSOR
  IS
  Select distinct ID
  from D_MP;

BEGIN 
  OPEN mul_pa_loop_CURSOR;
    LOOP
      OPEN mul_pa_ID_CURSOR;
       LOOP
          FETCH mul_pa_loop_cursor INTO pac_row;
            exit when mul_pa_loop_cursor%notfound;
            exit when mul_pa_ID_cursor%notfound;
            v_Num:= pac_row.Num;
            v_Amount:=pac_row.Amount/pac_row.Num;
        FOR i IN 1..v_Num
          LOOP
            INSERT INTO D_MP_1 ("BARCODE","Product", "Amount","ID","Num") 
            VALUES (pac_row."BARCODE",pac_row."Product",v_Amount,pac_row."ID",'1');
          END LOOP;
        COMMIT;
       END LOOP;
      CLOSE mul_pa_ID_CURSOR;
    END LOOP;
  CLOSE mul_pa_loop_CURSOR;
EXCEPTION
   WHEN OTHERS 
   THEN
      raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END MULTIPLE_CURSORS_TEST;

其实对于这个复制功能,一个游标就足够了。但我想根据此过程在促销活动的每个交易级别上做更多,所以我坚持使用这两个游标,mul_pa_LOOP_CURSOR 用于整行,另一个 mul_pa_ID_CURSOR 用于每个不同的交易 ID。

请随时对此程序发表评论。

我不明白你为什么有三个循环。

  • 第一个循环用于 "mul_pa_loop_CURSOR"
  • 第二个循环用于 "mul_pa_ID_CURSOR"
  • 第三个循环是数字的 FOR 循环

您仅从第一个循环中获取记录。至少根据您共享的代码,您的第二个循环似乎是多余的。尝试删除第二个循环或移动第一个循环中的 FETCH 和第一个 EXIT 语句,因为它们目前在第二个循环中。

OPEN mul_pa_loop_CURSOR;
  LOOP
    OPEN mul_pa_ID_CURSOR;
      LOOP
        FETCH mul_pa_loop_cursor INTO pac_row;   -- move this in first loop
        exit when mul_pa_loop_cursor%notfound;   -- move this in first loop
        exit when mul_pa_ID_cursor%notfound;    

像这样

OPEN mul_pa_loop_CURSOR;
  LOOP
    FETCH mul_pa_loop_cursor INTO pac_row;
    exit when mul_pa_loop_cursor%notfound;

    OPEN mul_pa_ID_CURSOR;
      LOOP
        -- There should be a separate FETCH statement for this loop
        exit when mul_pa_ID_cursor%notfound;    

希望对您有所帮助。

假设 num 总是整数,可以使用单个 SQL 查询来完成:

select barcode, product, amount/num as amount, 1 as num
from table1 t1
join (
  select level l from dual
  connect by level <= ( select max(num) from table1 )
) x
on x.l <= t1.num 
order by 1,2

BARCOD PRODUC     AMOUNT        NUM
------ ------ ---------- ----------
76Q7Q7 Water           5          1
76Q7Q7 Water           5          1
8JJ1CK Banana          2          1
8JJ1CK Banana          2          1
8JJ1NK Apple         5,5          1
8JJ1YK Orange        4,5          1

在 Oracle 12c 上,借助 LATERAL JOIN 甚至更容易:

select barcode, product, amount/num as amount, 1 as num
from table1 t1,
lateral (
  SELECT null FROM dual
  CONNECT BY LEVEL <= t1.num
) x
order by 1,2
;

BARCOD PRODUC     AMOUNT        NUM
------ ------ ---------- ----------
76Q7Q7 Water           5          1
76Q7Q7 Water           5          1
8JJ1CK Banana          2          1
8JJ1CK Banana          2          1
8JJ1NK Apple         5,5          1
8JJ1YK Orange        4,5          1