简体   繁体   中英

How to fetch the record from cursor

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.

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM