首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle隐式游标: for-else

Oracle隐式游标: for-else
EN

Stack Overflow用户
提问于 2013-12-02 14:29:29
回答 4查看 1.9K关注 0票数 1

这是一个非常基本的问题,但是在Oracle /SQL中将FORELSE写入隐式游标的最佳方法是什么?有些编程语言允许这种语法,在游标不返回任何行时执行FORELSE块。

我想要实现的是以下内容(伪代码):

代码语言:javascript
复制
DECLARE
    CURSOR test_cur IS
        SELECT 'a'
        FROM   table_with_zero_or_more_data;
BEGIN
    FOR r_ IN test_cur LOOP
        Dbms_Output.Put_Line ('One extra row found');
    FORELSE
        Dbms_Output.Put_Line ('No data found');
    END LOOP;
END;

我尝试过使用下面的异常,但是NO_DATA_FOUND异常不会由隐式游标触发。

代码语言:javascript
复制
DECLARE 
    CURSOR test_cur IS
        SELECT 'a'
        FROM   table_with_zero_or_more_data;
BEGIN
    BEGIN
        FOR r_ IN test_cur LOOP
            Dbms_Output.Put_Line ('One extra row found');
        END LOOP;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            Dbms_Output.Put_Line ('No data found');
    END;
END;

当然,下面的内容是有效的(我毫不怀疑,也有类似的变化)。但我发现这条路有点笨重。当代码变得更加真实和冗长时,IF语句链接到FOR循环并不是那么明显/直观。它还强制引入一个虚拟变量,只是在语法上不是很漂亮。

代码语言:javascript
复制
DECLARE 
    CURSOR test_cur IS
        SELECT 'a'
        FROM   table_with_zero_or_more_data;
    i NUMBER := 0;
BEGIN
    FOR r_ IN test_cur LOOP
        i := i + 1;
        Dbms_Output.Put_Line ('One extra row found');
    END LOOP;
    IF i = 0 THEN
        Dbms_Output.Put_Line ('No data found');
    END IF;
END;

我只是想知道是否有更好的方法,哪一种方法更直观,并集成了FORIF条件?

编辑

如果我还不够清楚的话,重点是在一个隐式游标中这样做。我知道我可以使用EXplicit游标和检查%NOTFOUND等(实际上%ROWCOUNT更好)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-12-03 07:00:42

AFAIK,因为PL/SQL缺少forelse构造,并且没有办法滚动您自己的构造,您可以期望的最好方法是使用额外的状态变量来满足隐式游标for-loop没有处理任何行的情况。

但是,您可以以这样的方式构造代码,更明显的是所发生的事情:

代码语言:javascript
复制
declare
  cursor test_c is
    with data_ as (
      select 1 as id, 'foo' as str from dual union all
      select 2 as id, 'bar' as str from dual
    )
    select str from data_ where id > 2;

  -- isolate the data processing into a dedicated subroutine/package
  -- pass all required information as parameters
  procedure process_data(p_data in test_c%rowtype) is
  begin
    dbms_output.put_line('processing: ' || p_data.str);
  end;
begin
  -- more things can take place here ...

  -- isolate the data processing into a dedicated block or subroutine
  -- with a block level comment like: processing all foos and bars to
  -- conform business rule car. (or even better: name the subroutine 
  -- accordingly !)
  declare
    v_has_data boolean := false;
  begin
    for d in test_c loop
      v_has_data := true;
      process_data(d);
    end loop;

    if not v_has_data then
      dbms_output.put_line('no data processed');
    end if;
  end;

  -- more things can take place here ...
end;
/

即使我也很同意这个错误..。这种方法的笨重之处请记住,所有编程语言都有权衡。

票数 4
EN

Stack Overflow用户

发布于 2013-12-02 14:41:25

尝试使用一个简单的循环并使用游标的%NOTFOUND属性进行测试,如下所示:

代码语言:javascript
复制
DECLARE 
    CURSOR test_cur IS
        SELECT 'a'
        FROM   table_with_zero_or_more_data;
    r_test test_cur%ROWTYPE;
BEGIN
    OPEN test_cur;

    FETCH test_cur INTO r_test;

    IF test_cur%NOTFOUND THEN
        dbms_output.put_line('No data found');
    ELSE
        LOOP
            FETCH test_cur INTO r_test;
            EXIT WHEN test_cur%NOTFOUND;
            dbms_output.put_line('One extra row found');
            -- 
            -- other routine code if there are rows found.
            -- 
        END LOOP;
    END IF;
END;
/

有关Oracle Docs的详细信息,请参阅FETCH

还可以在下面的评论中看到Nicholas的SQL。这很有帮助。

票数 1
EN

Stack Overflow用户

发布于 2013-12-02 16:06:56

类似的方法是使用游标的%ROWCOUNT属性。有关其他游标属性的引用,请使用链接elems011.htm,下面给出了使用ROWCOUNT实现的链接。

代码语言:javascript
复制
DECLARE 
CURSOR test_cur IS
    SELECT 'a'
    FROM   table_with_zero_or_more_data;
i NUMBER := 0;
r_test test_cur%ROWTYPE;
BEGIN
   OPEN test_cur;

LOOP
    FETCH test_cur INTO r_test;
    IF NOT test_cur%ROWCOUNT > 0 THEN
        dbms_output.put_line("No data found");
        EXIT;
    ELSE
        dbms_output.put_line("extra row found. Row count is now "||test_cur%ROWCOUNT);
    END IF;
    ...
    ... -- other routine code if there are rows found.
    ...
END LOOP;
END;
/
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20330690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档