PL / SQL检查SYS_REFCURSOR的大小

时间:2014-03-26 17:34:22

标签: oracle plsql sys-refcursor

我创建了一个返回SYS_REFCURSOR的oracle函数。问题是我需要返回的数据可能由两个不同的查询产生。基本上,如果第一个查询没有返回任何数据,那么我需要运行一个不同的查询,然后返回refcursor。

这是我的主意

    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;

无论出于何种原因if my_record_1%notfound检查都不起作用。我想我的问题是如何检查 my_record_1 光标是否包含任何数据?

谢谢

2 个答案:

答案 0 :(得分:2)

我注意到程序中使用的两个查询的一些常见功能:

光标查询选项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必须与table3具有相似的结构,因为两者在两个不同的查询中使用相同。

游标查询选项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
  

如果没有从选项1返回结果(未找到数据),则使用此查询(选项2)。它因查询的主表(table3)而异,并且添加了另一个INNER JOIN到table4

 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;
  

我还可以看到UNION或UNION ALL运算符如何也可以提供结果。在我的方法中,我利用JOINS来管理结果。

答案 1 :(得分:0)

我认为你可以通过使用FOR循环而不是使用%NOTFOUND来简化整个代码。     这是您可以尝试的示例代码示例。

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;