Reputation: 636
I am trying to fetch some records from Oracle using PL SOL cursor. This my code,
procedure parameter:
PT_CLAIMS IN CLIM_BEAN_TAB,
PO_CLAIMS_CUSROR OUT SYS_REFCURSOR
iteration code:
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;
I am using Out cursor in java. But whenever I iterate the out cursor using ResultSet am getting only one record.
How to add the values to cursor in the loop.
Upvotes: 0
Views: 1049
Reputation: 4538
This is because you are pulling claim id from the variable, if you want to pull all the claim ids that are inserted in the table then use select claim_id from TL_CLAIMS
. And you have to open cursor outside the loop if you want to pull all the CLAIM_IDs present in the table.
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;
UPDATE : Alternatively, if you want to get the list of all the claim ids generated within the code then you can write something like this.
FOR I IN 1 .. PT_CLAIMS.LAST LOOP
SELECT SEQ_TB_CLIAM.NEXTVAL INTO CLAIM_ID FROM DUAL;
IF I = 1 THEN
l_first_claim_id := CLAIM_ID;
END IF;
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 l_first_claim_id + ROWNUM - 1
FROM dual
CONNECT BY ROWNUM <= (CLAIM_ID - l_first_claim_id) + 1;
PS: Condition over here is the there are no simultaneous call from another session.
Upvotes: 2
Reputation: 191265
You are re-opening the OUT sys_refcursor each time you loop around the IN table contents. Each time the previous refcursor is discarded and a new one is created. (Hopefully Oracle is cleaning up the abandoned ones properly in the background).
When the loop exits the OUT parameter has the claim ID corresponding to the last entry in the IN table. You are not adding each claim ID to a single OUT refcursor - you can't do that.
You could maintain a local table of the generated IDs and then open the OUT cursor from that local table, after your loop. Or you could replace your loop with a single insert statement, in a forall
loop to allow you to use 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;
/
This uses a pre-defined type that is a varray of numbers; as it's an SQL type it can be used with the table()
(as a table collection expression).
SQL fiddle seems to be broken again, so a worked example in full:
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
Upvotes: 4
Reputation: 12440
SELECT CLAIM_ID AS CALIM_ID FROM DUAL;
will always return one row, since DUAL
only has a single row. So PO_CLAIMS_CUSROR
returning one row is expected behaviour.
Upvotes: 0