嵌套 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
简介:
我是 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