为啥 no_data_found ORA-01403 在 Oracle 中是一个异常?

Posted

技术标签:

【中文标题】为啥 no_data_found ORA-01403 在 Oracle 中是一个异常?【英文标题】:Why is no_data_found ORA-01403 an exception in Oracle?为什么 no_data_found ORA-01403 在 Oracle 中是一个异常? 【发布时间】:2011-04-25 19:51:10 【问题描述】:

如果 SELECT INTO 语句没有返回至少一行,则抛出 ORA-01403。

对于其他所有 DBMS,我知道这在 SELECT 上是正常的。 只有 Oracle 会这样对待 SELECT INTO。

CREATE OR REPLACE PROCEDURE no_data_proc IS
   dummy dual.dummy%TYPE;
BEGIN
  BEGIN 
     SELECT dummy  
       INTO dummy
       FROM dual
      WHERE dummy = 'Y';   
  EXCEPTION 
     WHEN no_data_found THEN
        dbms_output.put_line('Why is this needed?');
  END;
END no_data_proc;

为什么?

在我看来,你真的不需要这个例外。开销太大。 有时它很方便,但你必须编写一个完整的 BEGIN、EXCEPTION、WHEN、END 块。

有什么我看不到的根本原因吗?

【问题讨论】:

Don't forget to catch TOO_MANY_ROWS when the select returns more than one row. 【参考方案1】:

异常块不是需要,你可以根据上下文使用或不使用它。

在这里,您正在积极地忽略异常(该过程将成功返回),但大多数情况下,如果您正在执行 SELECT INTO,您希望它失败,如果它没有返回一行,考虑:

PROCEDURE update_employee_salary (p_empno) IS
   l_salary NUMBER;
BEGIN
   SELECT sal INTO l_salary FROM emp WHERE empno = p_empno FOR UPDATE;
   /* do something with emp data */
END;

如果使用 EMP 表中不存在的 empno 调用我的函数,我希望它失败。我可能会捕获异常以引发有意义的错误消息(使用raise_application_error),但大多数时候我对 ORA-01403 感到满意。

通常,您应该捕获的唯一异常是预期异常(即,这不应该是捕获所有 ORA-01403 或所有异常的标准)。

【讨论】:

【参考方案2】:

但是我们仍然需要回答“为什么在SELECT没有数据要检索的情况下会抛出异常”的问题。

我相信这样做是因为这是一种常见的情况,否则可能会被忽视。编写代码,就好像它总是希望找到数据是一种常见的事情,如果我们应该进行错误检查,例如

SELECT <something...>
IF SQLCODE = 100 THEN -- No data found
  <no-data handler>
END IF

恕我直言,SQLCODE = 100 的检查可能会经常被跳过。提出一个异常会让你一头雾水:A)发生了重要情况(没有找到数据),B)没有为此做任何准备。 IMO 让 PL/SQL 引擎引发异常比让程序愉快地继续运行要好于假设数据已被检索而实际上并未检索到,这可能会导致各种其他问题。

分享和享受。

【讨论】:

【参考方案3】:

您可以尝试使用 MIN 来避免使用 EXCEPTION 子句。

 SELECT MIN(dummy)  
   INTO dummy
   FROM dual
  WHERE dummy = 'Y'; 

那么虚拟变量将为NULL

【讨论】:

如果行数过多怎么办?然后你会选择可能是错误的最小行。 @user411718,如果您希望有几行,为什么还要尝试将其存储在变量中?我只在可以得到一行或没有行的情况下使用 MIN,以避免使用 EXCEPTION。而我需要的是:只是一个值或 NULL。【参考方案4】:

因为您正在执行 SELECT INTO ,它只需要一行(更多行也是错误的)。

如果你可以有一行或没有行,你可以使用游标。

数据库的工作不是为您确定缺少的行不是错误,只需将值设置为 null。

【讨论】:

有使用游标的例子吗?【参考方案5】:

您还可以使用 sql MAXMIN 函数。如果没有返回行,那么这些函数将返回 NULL

例如: 选择 MAX(第 1 列) 进入变量 从表 其中 Column1 = '值';

MAX函数将返回最大值,如果没有返回行则返回NULL。

【讨论】:

【参考方案6】:

因为不清楚 PL/SQL 引擎应该做什么 - 它应该退出块吗?它应该在变量中使用 NULL 吗?如果在下一个块中您尝试将其插入到 NOT NULL 列中,它应该如何报告错误的位置?将其设为例外会迫使您明确说明它。

【讨论】:

【参考方案7】:

MAX 函数工作它不会抛出错误 ORA-01403 当 select INTO 返回 NULL 时工作

【讨论】:

欢迎来到 SO @Gaurav,最好包含相关的源代码以支持您的答案...

以上是关于为啥 no_data_found ORA-01403 在 Oracle 中是一个异常?的主要内容,如果未能解决你的问题,请参考以下文章

No_data_found 异常处理

PL SQL 过程不引发异常 no_data_found

oracle 中的 No_Data_found 异常

No_data_found 异常也传播到外部块?

PL/SQL 中的子查询返回 NO_DATA_FOUND

mybatis 调用 oracle 存储过程 select into 无记录时NO_DATA_FOUND异常处理分析