为啥 PLSQL 中的代码在“异常”部分之后没有执行?

Posted

技术标签:

【中文标题】为啥 PLSQL 中的代码在“异常”部分之后没有执行?【英文标题】:Why is code in PLSQL not executing after "exception" part?为什么 PLSQL 中的代码在“异常”部分之后没有执行? 【发布时间】:2020-12-26 16:37:28 【问题描述】:

所以我犯了一个错误,我没有在嵌套的 begin-end 块中立即执行,所以我的代码不起作用。所以基本上我有

begin
 execute immediate 'select * from sales';
 exception when others then null;
 dbms_output.put_line(123);
end;

Dbms_output 没有打印“123”,我发现我需要在 begin-end 中立即执行。我想确定,所以我的问题是为什么即使没有引发异常,代码也不会在异常部分之后执行?

【问题讨论】:

无法复制,因为抛出异常。 db<>fiddle 我目前在DataGrip工作,这是一张照片example@MT0 在运行 PL/SQL 匿名块之前尝试运行 SET SERVEROUTPUT ON; 以显示控制台输出。 您的 dbms_output 是异常的一部分,它将在不执行任何操作的“null”部分之后执行。你有一个叫做销售的表吗?如果是,那么您的立即执行不会引发错误,因此 dbms_output 不会被执行。 @wemfried,不,如果没有 into 子句,它不会引发异常。注释 dbfiddle 中的异常行,然后尝试(将 sales 替换为 dual 后) 【参考方案1】:

为什么即使没有引发异常,代码也没有在异常部分之后执行?

原因很简单——问题中的dbms_output.put_line不在“异常部分之后”

正确缩进的代码相当于:

begin
    execute immediate 'select * from dual';
exception when others then 
    null;
    dbms_output.put_line(123);
end;
/

异常块是EXCEPTIONSEND; 之间的所有内容,如果发生异常将被执行。

【讨论】:

【参考方案2】:

这里有几件事在起作用 - 解析和执行。

如果表不存在,则无法解析该语句,因此我们会立即得到一个异常。

SQL> begin
  2     execute immediate 'select * from xxxx';
  3  end;
  4  /
begin
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at line 2

但是,如果表确实存在,那么解析就可以了。因为您从未指定过我们所做的所有的INTO。我们从来不需要执行和开始获取阶段,因此没有发生错误。一个容易看出我们从未执行过该语句的方法是使用类似

SQL> begin
  2     execute immediate 'select 1/count(*) from dual where 1=2';
  3  end;
  4  /

PL/SQL procedure successfully completed.

如果我们已经执行,那么我们预计会出现除以零的错误。当我们看到 INTO 时,我们需要获取(这将需要执行)。

【讨论】:

我明白了,但上面的代码只是示例,在我的实际代码中我已经进入。请查看我上面在源问题 cmets 中的最后一条评论,我在其中解释了我发现非常奇怪的事情。至少对我来说。 你唯一的工作与否的证据是看到 dbms_output.put_line 的输出。但这是您必须了解的基本原理。 dbms_output.put_line 写入控制台,它写入内部缓冲区。然后在程序完成后,调用客户端可以(或不可以)选择如何处理该缓冲区。有些客户总是忽略它。 当且仅当您已发出“set serverout on”命令时,sqlplus 才会选择处理和显示它。 @EdStevens 我明白了,你是对的。但是,当引发异常而不是未引发异常时,相同的代码如何工作?那么当引发异常时,DataGrip 显示内部缓冲区,而当未引发异常时,它会忽略它?

以上是关于为啥 PLSQL 中的代码在“异常”部分之后没有执行?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们需要在最后写 WHEN OTHERS THEN 异常 - Oracle PLSQL [关闭]

无法在plsql中打印异常

plsql定时任务执行失败

为啥 PLSQL 比 SQL*Plus 慢

PLSQLOracle中的异常

Java里面用try catch异常处理之后,catch之后的代码也会执行,那还要finally有啥用啊?