我正在尝试使用PL SOL游标从Oracle获取一些记录。这是我的代码,
程序参数:
FOR I IN 1 .. PT_CLAIMS.LAST LOOP
SELECT SEQ_TB_CLIAM.NEXTVAL INTO CLAIM_ID FROM DUAL;
INSERT INTO TL_CLAIMS
(
CLAIM_ID,
CLAIM_USER,
CLAMIANT_ID
)
VALUES(
CLAIM_ID,
PT_CLAIMS(I).USER_ID,
PT_CLAIMS(I).CLAMIANT_ID
);
OPEN PO_CLAIMS_CUSROR FOR
SELECT CLAIM_ID AS CALIM_ID FROM DUAL;
end loop;
迭代代码:
(-1000, 1000)
我在java中使用Out游标。但每当我使用ResultSet迭代out游标时,我只获得一条记录。
如何在循环中将值添加到游标。
答案 0 :(得分:4)
每次循环IN表内容时,都会重新打开OUT sys_refcursor。每次丢弃前一个refcursor并创建一个新的refcursor。 (希望Oracle正在后台正确清理被遗弃的那些)。
当循环退出时,OUT参数的声明ID对应于IN表中的最后一个条目。您没有将每个声明ID添加到单个OUT refcursor中 - 您不能这样做。
您可以维护生成的ID的本地表,然后在循环之后从该本地表打开OUT游标。或者您可以在forall
循环中使用单个insert语句替换循环,以允许您使用returning bulk collect into
:
create procedure p42(pt_claims in claim_bean_tab,
po_claims_cursor out sys_refcursor)
as
l_claim_ids sys.odcinumberlist;
begin
forall i in 1..pt_claims.count
insert into tl_claims(claim_id, claim_user_id, claimant_id)
values (seq_tb_claim.nextval, pt_claims(i).user_id, pt_claims(i).claimant_id)
returning claim_id bulk collect into l_claim_ids;
open po_claims_cursor for
select column_value from table(l_claim_ids);
end;
/
这使用了一个预定义的类型,它是一个数字的变种;因为它是一种SQL类型,它可以与table()
一起使用(作为table collection expression)。
SQL小提琴似乎再次被打破,所以一个完整的例子:
create type claim_bean as object (user_id number, claimant_id number);
/
create type claim_bean_tab as table of claim_bean;
/
create table tl_claims (claim_id number, claim_user_id number, claimant_id number)
/
create sequence seq_tb_claim;
/
create procedure p42(pt_claims in claim_bean_tab,
po_claims_cursor out sys_refcursor)
as
l_claim_ids sys.odcinumberlist;
begin
forall i in 1..pt_claims.count
insert into tl_claims(claim_id, claim_user_id, claimant_id)
values (seq_tb_claim.nextval, pt_claims(i).user_id, pt_claims(i).claimant_id)
returning claim_id bulk collect into l_claim_ids;
open po_claims_cursor for
select column_value from table(l_claim_ids);
end;
/
set serveroutput on
declare
l_claims claim_bean_tab;
l_claims_cursor sys_refcursor;
l_claim_id tl_claims.claim_id%type;
begin
l_claims := new claim_bean_tab();
l_claims.extend(3);
l_claims(1) := new claim_bean(42, 123);
l_claims(2) := new claim_bean(57, 456);
l_claims(3) := new claim_bean(13, 789);
p42(l_claims, l_claims_cursor);
loop
fetch l_claims_cursor into l_claim_id;
exit when l_claims_cursor%notfound;
dbms_output.put_line('Got claim ID from cursor: ' || l_claim_id);
end loop;
close l_claims_cursor;
end;
/
select * from tl_claims
/
PL/SQL procedure successfully completed.
Got claim ID from cursor: 1
Got claim ID from cursor: 2
Got claim ID from cursor: 3
答案 1 :(得分:2)
这是因为您要从变量中提取声明ID,如果要拉出表中插入的所有声明ID,请使用 pw.print(ss);
。如果要拉出表中存在的所有CLAIM_ID,则必须在循环外部打开游标。
select claim_id from TL_CLAIMS
UPDATE:或者,如果您想获取代码中生成的所有声明ID的列表,那么您可以编写类似的内容。
FOR I IN 1 .. PT_CLAIMS.LAST LOOP
SELECT SEQ_TB_CLIAM.NEXTVAL INTO CLAIM_ID FROM DUAL;
INSERT INTO TL_CLAIMS
(
CLAIM_ID,
CLAIM_USER,
CLAMIANT_ID
)
VALUES(
CLAIM_ID,
PT_CLAIMS(I).USER_ID,
PT_CLAIMS(I).CLAMIANT_ID
);
end loop;
OPEN PO_CLAIMS_CUSROR FOR
SELECT CLAIM_ID FROM TL_CLAIMS;
PS:此处的条件是没有来自另一个会话的同时呼叫。
答案 2 :(得分:0)
SELECT CLAIM_ID AS CALIM_ID FROM DUAL;
总是返回一行,因为DUAL
只有一行。因此PO_CLAIMS_CUSROR
返回一行是预期的行为。