DBMS_OUTPUT 未使用游标获取输出中的任何行

Posted

技术标签:

【中文标题】DBMS_OUTPUT 未使用游标获取输出中的任何行【英文标题】:DBMS_OUTPUT not fetching any rows in output using cursor 【发布时间】:2019-04-25 07:10:10 【问题描述】:

DBMS_OUTPUT.PUT_LINE 在使用光标时没有返回数据,如下代码所示

我使用布尔值来比较表中的金额

SET SERVEROUTPUT ON; 
DECLARE
    --declaration of variable
     x_id        test.saa.id%TYPE;
     x_acctname   test.saa.acctname%TYPE;
     x_curbal      test.saa.balamt%TYPE;
     x_sid       test.saa.sid%TYPE;

--setting of the boolean value default to null
     b_lowamount   BOOLEAN := false;

    --declaration of cursor
    CURSOR custbal IS
    SELECT id,acctname,bal_amt,sid
    FROM
        test.saa WHERE ROWNUM <= 1000;
   BEGIN 
                  --checking cursor is open or not
                     IF NOT ( custbal%isopen ) THEN
                           OPEN custbal;
                      END IF; 
    LOOP
    FETCH custbal INTO
                  x_id,
                  x_acctname,
                  x_curbal,
                 x_sid;
EXIT WHEN custbal%notfound;
CONTINUE WHEN custbal%found;
--begin another 
BEGIN
    b_lowamount   := ( x_curbal < 10 );
    IF b_lowamount THEN
        dbms_output.put_line('The customer having '|| x_acctname|| ' with sol_id '|| x_sid|| 'with balance RS. '|| x_curbal);

    ELSE
        dbms_output.put_line('The customer having '|| x_acctname|| ' with sol_id '|| x_sid|| 'with balance RS. '|| x_curbal);
        END IF;
      END;
 END loop;
 end;

虽然程序成功完成,但没有返回任何内容

【问题讨论】:

【参考方案1】:

没有显示您的输出的原因是因为CONTINUE - 这意味着转到下一个循环的开始。

相反,您的程序可以写成:

DECLARE
  --declaration of variable
  x_id       test.saa.id%TYPE;
  x_acctname test.saa.acctname%TYPE;
  x_curbal   test.saa.balamt%TYPE;
  x_sid      test.saa.sid%TYPE;

  --setting of the boolean value default to null
  b_lowamount BOOLEAN := FALSE;

  --declaration of cursor
  CURSOR custbal IS
    SELECT id,
           acctname,
           bal_amt,
           sid
    FROM   test.saa
    WHERE  rownum <= 1000;
BEGIN
  OPEN custbal;

  LOOP
    FETCH custbal
      INTO x_id,
           x_acctname,
           x_curbal,
           x_sid;
    EXIT WHEN custbal%NOTFOUND;

    b_lowamount := (x_curbal < 10);
    IF b_lowamount
    THEN
      dbms_output.put_line('The customer having ' || x_acctname || ' with sol_id ' || x_sid || 'with balance RS. ' || x_curbal);

    ELSE
      dbms_output.put_line('The customer having ' || x_acctname || ' with sol_id ' || x_sid || 'with balance RS. ' || x_curbal);
    END IF;
  END LOOP;

  CLOSE custbal;
END;
/

注意我已经删除了循环中多余的BEGINEND;无需在当前区块内开始新区块!

另外,我已经删除了您对游标是否打开的检查(它将始终在匿名块的开头关闭,因为游标完全在匿名块的范围内声明,并且 Oracle 关闭范围结束后的变量。但是,我添加了一个显式的CLOSE 语句来关闭游标。这不是严格需要的(因为一旦块完成,游标将自动关闭),但这是一个好习惯如果您手动打开光标,则将其包含在内。

但是,您的整个过程可以简化为:

BEGIN
  FOR rec IN (SELECT id,
                     acctname,
                     bal_amt,
                     sid
              FROM   test.saa
              WHERE  rownum <= 1000)
  LOOP
    IF rec.bal_amt < 10
    THEN
      dbms_output.put_line('The customer having ' || rec.acctname || ' with sol_id ' || rec.sid || 'with balance RS. ' || rec.curbal);
    ELSE
      dbms_output.put_line('The customer having ' || rec.acctname || ' with sol_id ' || rec.sid || 'with balance RS. ' || rec.curbal);
    END IF;
  END LOOP;
END;
/

(我保留了 IF 语句原样,即使两个分支都输出相同的字符串 - 我认为这是一个错误,并且您的意思是要输出不同的文本,具体取决于余额小于 10还是不要?如果没关系,你可以去掉IF语句,直接输出结果。)

游标 for 循环的好处是你不需要声明变量来返回值(记录是作为FOR &lt;record&gt; in (&lt;cursor&gt;) 语句的一部分隐式创建的),你不需要处理光标的打开和关闭。它还使您的代码更简单,因此 - IMO - 更易于理解和维护。

【讨论】:

谢谢在删除 EXIT WHEN 条件后它起作用了 但它在 dbms_output 的所有行中返回了相同的表记录Alternative way is working Properly . 到底为什么要删除 exit when 子句?这意味着你会进入一个无限循环! 这样做之后我进入了无限循环,但 dbms_output 的所有记录都返回相同 这不足为奇;如果您没有获取行但由于没有 n 退出条件而仍在循环,则在获取最后一行后变量中的值不会改变。总之,把exit when子句放回去!!! 伟人

以上是关于DBMS_OUTPUT 未使用游标获取输出中的任何行的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE中如何用DBMS_OUTPUT包输出表的所有数据

oracle游标的使用

带有隐式游标的过程正在编译但未打印

oracle游标使用遍历3种方法

后台处理程序未将 dbms_output 写入文件

存储过程的dbms_output.put_line问题