Domanda

I have created an oracle function that returns SYS_REFCURSOR. The issue is that data which I need to return may be produced by two different queries. Basically if first query returns no data then I need to run a different query and then return refcursor.

Here is my big idea

    FUNCTION F_RETURN_RECORD(
              P_VAL in NUMBER)  
                RETURN SYS_REFCURSOR AS TYPE R_CURSOR IS REF CURSOR;
                my_record_1 R_CURSOR;
                processed_record R_CURSOR;
         BEGIN
          OPEN my_record_1 FOR select e.COL1, e.COL2,a.COL1,e.COL3, e.COL4, 
                                         e.COL5, e.COL6, e.COL7, e.COL8, e.COL9,
                                         e.COL10, e.COL11
                                  from table1 e
                                  inner join table2 a on e.COL2=a.COL2
                                  where e.COL1=P_VAL;

          if my_record_1%notfound
            then
                close my_record_1;
                OPEN processed_record for select e.COL1, e.COL2,a.COL1,e.COL3, e.COL4, 
                                         e.COL5, e.COL6, e.COL7, e.COL8, e.COL9,
                                         e.COL10, e.COL11, e.COL12, e.COL13, e.COL14
                                  from table3 e
                                  inner join table2 a on e.COL2=a.COL2
                                  inner join table 4 b on a.col1=b.col2
                                  where e.COL1=P_VAL;                                   
                return processed_record;
          end if;
          DBMS_OUTPUT.PUT_LINE('Returning data.................');

          return my_record_1;       
 END F_RETURN_RECORD;

For whatever reason if my_record_1%notfound check doesn't work. I guess my question is how can I check if my_record_1 cursor doesn't contain any data?

Thank you

È stato utile?

Soluzione

I noticed some common features of the two queries used in the procedure:

Cursor query option 1:

 select e.COL1, e.COL2,a.COL1,e.COL3, e.COL4, 
     e.COL5, e.COL6, e.COL7, e.COL8, e.COL9,
     e.COL10,e.COL11, e.COL12, e.COL13, e.COL14
   from table1 e
  where e.COL1=P_VAL;                                 

 inner join table2 a on e.COL2=a.COL2

table1 must have similar structure to table3 because both are used identically in the two different queries.

Cursor query option 2:

 select e.COL1, e.COL2,a.COL1,e.COL3, e.COL4, 
     e.COL5, e.COL6, e.COL7, e.COL8, e.COL9,
     e.COL10,e.COL11, e.COL12, e.COL13, e.COL14
   from table3 e
  where e.COL1=P_VAL;                                 

 inner join table2 a on e.COL2=a.COL2
 inner join table4 b on a.col1=b.col2

If no results come back from option 1 (no data found), this query (option 2) is used. It differs by the primary table queried (table3) and an additional INNER JOIN to table4 is added.

 FUNCTION F_RETURN_RECORD (P_VAL IN NUMBER) RETURN SYS_REFCURSOR AS TYPE R_CURSOR
    IS REF CURSOR;
    my_record_1        R_CURSOR;
    processed_record   R_CURSOR;

 BEGIN

 OPEN my_record_1 FOR

 WITH        
    OPT1 AS (SELECT e.col1, e.col2, e.col3, e.col4, ..., e.col14
               FROM table1 e
              INNER JOIN table2 a on e.col2 = a.col2
              WHERE e.col1 = P_VAL),

    OPT2 AS (SELECT e.col1, e.col2, e.col3, e.col4, ..., e.col14
               FROM table1 e
              INNER JOIN table2 a on e.col2 = a.col2
              INNER JOIN table4 b on a.col1 = b.col2
              WHERE e.col1 = P_VAL),

    SELECT NVL(opt1.col1, opt2.col1) as col1,
       NVL(opt1.col2, opt2.col2) as col2,
       NVL(opt1.col3, opt2.col3) as col3,
       NVL(opt1.col4, opt2.col4) as col4,
        ....

       NVL(opt1.col3, opt2.col3) as col13,
       NVL(opt1.col4, opt2.col4) as col14

      FROM OPT2
      LEFT OUTER JOIN OPT1 on OPT2.col1 = OPT1.col1;

      return my_record_1;

  END F_RETURN_RECORD;

I could also see how a UNION or UNION ALL operator might have also served the result. In my approach, I leveraged JOINS to manage the results.

Altri suggerimenti

I think you can simplify the whole code by just using FOR loop instead of using %NOTFOUND. This is an example of this sample code you can try.

CREATE OR REPLACE FUNCTION F_RETURN_RECORD(
    P_VAL IN NUMBER)
  RETURN SYS_REFCURSOR
AS
TYPE R_CURSOR
IS
  REF
  CURSOR;
    my_record_1 R_CURSOR;
    processed_record R_CURSOR;
    cur_count NUMBER;
  BEGIN
    cur_count:=0;
    --OPEN my_record_1 FOR select * FROM AVRAJIT;
    FOR rec IN
    (SELECT query
    )
  LOOP
    cur_count:=cur_count+1;
  END LOOP;
  --if my_record_1%notfound
  --then
  -- close my_record_1;
  IF cur_count <> 1 THEN
    OPEN processed_record FOR SELECT query;
    RETURN processed_record;
  END IF;
  DBMS_OUTPUT.PUT_LINE('Returning data.................');
  RETURN my_record_1;
END F_RETURN_RECORD;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top