除了 no_data_needed 之外,是否还有其他异常被 oracle 捕获?

Is there other exceptions than no_data_needed that are caught under the hood by the oracle?

信息:

当您查询应该 return n 个元素的流水线函数时,也会出现不需要数据的情况。但是您添加了条件 nb_row< m 和 m

例如:

select *
    from table ( my_pieplined_function())  -- this function should returns 20 elements
   where rownum < 10;

它应该与 fetch next n rows only 一起出现。但我已经测试过了。

我了解到我不需要处理流水线函数中发生的异常“no_data_needed”。当我进行查询时,逻辑上 oracle 会捕获此异常,获取已通过管道传输的行,对其余行不执行任何操作。

让oracle捕获异常就相当于那个

create my_pieplined_function return sys.odcinumberlist is
    i integer:=0;
begin
    for loop
        pipe row (i); 
        i:=i+1;
        if i=20 then return i; end;
    end loop;
exception
      when no_data_needed then   null;
end;

那里有更多信息https://asktom.oracle.com/Misc/nodataneeded-something-i-learned.html

问题

我想知道是否还有其他异常可以被 oracle 捕获而无需执行任何操作。如果是,我在哪里可以找到这些例外的列表。

其他问题:

为什么我在[预定义异常摘要] (https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/07_errs.htm)

中找不到 no_data_needed

why don't I find no_data_needed in [summary of predefined exception] (https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/07_errs.htm)

因为那个版本没有记录。

它在 Oracle 11g Database PL/SQL Language Reference.


I have learned that I don't need to handle the exception no_data_needed that occurs in a pipelined function.

如果在流水线函数之后清理时没有任何需要做的事情,则不需要处理该异常。

如果你这样做:

CREATE FUNCTION my_pipelined_function
RETURN sys.odcinumberlist PIPELINED
IS
BEGIN
  DBMS_OUTPUT.PUT_LINE( 'Initialise' );
  FOR i IN 1 .. 2 LOOP
    DBMS_OUTPUT.PUT_LINE( 'Loop ' || i );
    pipe row (i);
  END LOOP;

  DBMS_OUTPUT.PUT_LINE( 'Cleanup' );
  RETURN;
END;
/

如果调用该函数,则使用:

SELECT * FROM TABLE(my_pipelined_function());

则输出为:

COLUMN_VALUE
1
2
Initialise
Loop 1
Loop 2
Cleanup

但是如果你限制行数:

SELECT * FROM TABLE(my_pipelined_function()) WHERE rownum = 1;

那么输出将是:

COLUMN_VALUE
1
Initialise
Loop 1

并且 Cleanup 部分永远不会到达,因为您在循环中间停止调用该函数。

如果您将函数定义为:

CREATE FUNCTION my_pipelined_function
RETURN sys.odcinumberlist PIPELINED
IS
BEGIN
  DBMS_OUTPUT.PUT_LINE( 'Initialise' );
  FOR i IN 1 .. 2 LOOP
    DBMS_OUTPUT.PUT_LINE( 'Loop ' || i );
    pipe row (i);
  END LOOP;

  DBMS_OUTPUT.PUT_LINE( 'Cleanup 1' );
  RETURN;
EXCEPTION
  WHEN NO_DATA_NEEDED THEN
    DBMS_OUTPUT.PUT_LINE( 'Cleanup 2' );
    RETURN;
END;
/

并使用以下方式调用它:

SELECT * FROM TABLE(my_pipelined_function()) WHERE rownum = 1;

那么输出将是:

COLUMN_VALUE
1
Initialise
Loop 1
Cleanup 2

因此,如果您的流水线函数在函数完成时无事可做,则无需处理该异常;但是,如果您初始化某些东西并需要在函数结束时清理它,那么您应该处理 NO_DATA_NEEDED 异常,因为它允许您在循环提前终止时执行清理。

db<>fiddle here


I would like to know if there are other exception that are caught by oracle without having to do something.

在SQL范围内(而不是PL/SQL范围内),Oracle会默默地捕获NO_DATA_FOUND异常并用NULL值替换它:

例如:

SELECT (SELECT 1 FROM DUAL WHERE 1 = 0) AS value
FROM   DUAL;

外部查询需要一个值:

SELECT <something> AS value
FROM   DUAL;

内部查询:

SELECT 1 FROM DUAL WHERE 1 = 0

生成零行,因此没有值;这引发了一个 NO_DATA_FOUND 异常,该异常被静默捕获并替换为 NULL 值。

这可以通过以下方式更清楚地看到:

WITH FUNCTION ndf RETURN NUMBER
  IS
  BEGIN
    RAISE NO_DATA_FOUND;
  END;
SELECT ndf() AS value FROM DUAL;

输出:

VALUE
null

PL/SQL 中的行为不同:

DECLARE
  v_value NUMBER;
BEGIN
  SELECT 1 INTO v_value FROM DUAL WHERE 1 = 0;
END;
/

不会捕获 NO_DATA_FOUND 异常,它会导致块的执行提前终止。