PL/SQL:是否有完全停止脚本执行的指令?

Fro*_*y Z 12 oracle plsql exit-code

我正在尝试在PL/SQL脚本开头对数据库模式进行一些检查.

如果检查结果不成功,我想停止脚本,以防止执行下一条指令.

我得到了这样的东西

-- 1st line of PL/SQL script

DECLARE
  SOME_COUNT INTEGER;
BEGIN
  SELECT COUNT(*) INTO SOME_COUNT FROM SOME_TABLE WHERE <SOME_CONDITIONS>;
  IF (SOME_COUNT > 0) THEN
    DBMS_OUTPUT.PUT_LINE('Test failed, I don''want the rest of the script'
      || ' to be executed.');
    --EXIT or something like that?... <= STOP EXECUTION HERE
  END IF;
END;
/

-- OTHER SQL INSTRUCTIONS...
ALTER TABLE SOME_TABLE ...
Run Code Online (Sandbox Code Playgroud)

我正在寻找允许做" STOP EXECUTION HERE" 的指令.

cod*_*eim 12

基于这个问题,我不同意接受的答案.该问题显示了一个多语句批处理脚本.RAISE_APPLICATION_ERROR()仅退出PL/SQL块(子程序),而不是从整个脚本中退出(正如Justin所指出的那样),因此它将继续使用后面的语句.

对于批处理脚本,最好使用WHENEVER SQLERROR EXIT.是的,它是一个SQL*Plus指令,而不是标准的SQL,但是相当便携; 支持脚本的最流行的Oracle工具至少部分支持该指令.以下示例适用于SQL*Plus,SQL*Developer,Toad,SQLsmith以及可能的其他示例,如果您对该行进行注释,则演示此问题.

set serveroutput on

-- Without this line, things keep going
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK;

BEGIN
  IF (1 > 0) THEN
    DBMS_OUTPUT.PUT_LINE('First thing');
    RAISE_APPLICATION_ERROR(-20000, 'Test failed'); -- not enough
  END IF;
END;
/

-- This will execute if you remove WHEN SQLERROR.., so RAISE_APPLICATION_ERROR is not enough
BEGIN
   DBMS_OUTPUT.PUT_LINE('Second thing - Executes anyway');
END;
/
Run Code Online (Sandbox Code Playgroud)

如果删除WHEN SQLERROR,脚本将继续并执行第二个块等,这正是问题要避免的问题.

在这种情况下,模拟sqlplus的图形工具的优点是它们确实停止了脚本,并且不会将脚本的其余部分作为shell命令提交给命令shell,如果将脚本粘贴到SQL*中会发生这种情况.另外在控制台窗口中运行.SQL*Plus可能会在出错时退出,但其余的缓冲命令将由OS shell处理,如果您在注释中有shell命令(这并非闻所未闻),这有点混乱并且可能存在风险.使用SQLPlus,最好连接,然后执行脚本,或者在<start>命令行参数(sqlplus scott/tiger @ foo.sql)中传递它以避免这种情况.


tbo*_*one 8

如果您不想引发异常,可以尝试类似(未经测试):

declare
  SOME_COUNT INTEGER;
begin
  SELECT COUNT(*) INTO SOME_COUNT FROM SOME_TABLE WHERE <SOME_CONDITIONS>;
  IF (SOME_COUNT > 0) THEN
    DBMS_OUTPUT.PUT_LINE('Test failed, I don''want the rest of the script'
      || ' to be executed.');

    goto end_proc;
  END IF;

  -- A bunch of great code here

  <<end_proc>>
  null;  -- this could be a commit or other lines of code
end;
Run Code Online (Sandbox Code Playgroud)

有些人讨厌任何GOTO声明,因为如果被滥用会导致意大利面条代码,但在这样的简单情况下(再次,假设你不想提出异常),他们的工作效果很好.


Fro*_*y Z 5

几秒钟的谷歌搜索给了我答案:功能 RAISE_APPLICATION_ERROR()

  IF (SOME_COUNT > 0) THEN
    RAISE_APPLICATION_ERROR(-20000, 'Test failed');
  END IF;
Run Code Online (Sandbox Code Playgroud)

用户定义的错误代码应介于-20000和-20999之间.

有关Oracle doc的详细信息,请访问:http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/07_errs.htm#877(定义自己的错误消息:过程RAISE_APPLICATION_ERROR)

  • 如果你在你的问题中发布的代码中使用`raise_application_error`,它将使你脱离PL/SQL块,但仍然会执行`OTHER SQL INSTRUCTIONS`部分.这就是你追求的吗? (2认同)