为啥 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;
/
异常块是EXCEPTIONS
和END;
之间的所有内容,如果发生异常将被执行。
【讨论】:
【参考方案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 中的代码在“异常”部分之后没有执行?的主要内容,如果未能解决你的问题,请参考以下文章