【问题标题】:PL/SQL check size of SYS_REFCURSORSYS_REFCURSOR 的 PL/SQL 检查大小
【发布时间】:2014-03-26 17:34:21
【问题描述】:

我创建了一个返回 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 光标是否不包含任何数据?

谢谢

【问题讨论】:

  • %notfound% 在从游标中获取之前没有意义。我不认为你可以做你正在尝试的事情。您现在可能有一个查询,在两者之间有一个 union all,另外还有一个 exists 检查?
  • 示例查询的编写方式看起来像是某种分支决策逻辑...使用查询 1...如果没有结果,请尝试其他查询...正确吗?

标签: oracle plsql sys-refcursor


【解决方案1】:

我注意到该过程中使用的两个查询的一些共同特征:

光标查询选项 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 - 你的答案更好 - 我正在删除我的。除了 - 我不认为你想在 proc 结束时关闭光标 - 只需将它打开即可。分享和享受。
  • 谢谢@BobJarvis!我编辑了查询以反映您的建议。
【解决方案2】:

我认为你可以通过只使用 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;

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    相关资源
    最近更新 更多