2014-03-26 29 views
1

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

这里是我的大创意

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游标不包含任何数据?

谢谢

+1

'%notfound%'只有在从游标中获取时才有意义。我不认为你可以做你想做的事。你也许可以在你现在两个人之间用'union all'查询一个单独的查询,并附加'exists'检查? –

+0

您的示例查询写入的方式看起来像某种分支决策逻辑...使用查询1 ...如果没有结果,请尝试另一个查询...是否正确? –

回答

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必须具有相似的结构因为二者在两个不同的查询中使用相同。

光标查询选项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来管理结果。

+0

+1 - 你的答案更好 - 我删除我的。除了 - 我不认为你想在proc结束时关闭游标 - 只要将它打开即可。分享并享受。 –

+0

谢谢@BobJarvis!我编辑了查询以反映您的建议。 –

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;