繁体   English   中英

如何在发生错误时退出SQLPlus中的脚本并返回SQLPlus提示符,而不断开连接或退出SQLPlus?

[英]How do I exit a script in SQLPlus when an error occurs and return to the SQLPlus prompt, without disconnecting or exiting SQLPlus?

我有一些经常运行的脚本,总是来自连接的SQLPlus会话。

我需要一种方法在发生错误时退出脚本, 而无需断开或退出SQLPlus本身。 100%的情况下,当发生错误时,连接的DBA将需要向会话发出一个或多个命令。 100%的时间,当发生错误时,脚本中有其他SQLPlus语句(因此必须BEGIN..END; 之外 BEGIN..END; )以后必须不执行或者可能出现严重问题。

注意:如果您建议WHENEVER SQLERROR EXIT那么您没有阅读上述文本。 除了脚本之外,这将断开并退出SQLPlus,这是不可接受的行为。

我在这里找到了一个有趣的想法,当它与spencer7593的答案相结合时,会给我一个选择性的子脚本调用,我可以传递PL / SQL输出值。 以机智:

VAR continue number;
EXEC :continue := 1;
BEGIN
   SELECT some_bool_test() INTO :continue FROM dual;
END;

SET termout OFF
COLUMN script_name NEW_VALUE v_script_name
SELECT decode(:continue, 1, 'run_stuff.sql', 'skip.sql') script_name FROM dual;
SET termout ON

@&v_script_name :some_other_values

其中skip.sql是一个空文本文件。

更新:我已将大部分内容转移到RUN.SQL文件中,其中我将布尔值(0或1)作为&1传递,脚本名称作为&2调用成功,然后将任何其他预期参数传递给叫脚本。 因此,它最终看起来像这样:

VAR continue number;
EXEC :continue := 1;
BEGIN
   SELECT some_bool_test() INTO :continue FROM dual;
END;

@run.sql :continue 'run_stuff.sql' :some_other_values

这是不可能的。

SQLPlus不提供对脚本执行的控制级别。

显然,您需要使用WHENEVER SQLERROR EXIT ...命令进行避免。

通过使用PL / SQL引发异常(错误),可以获得对哪些SQL语句执行或不执行的条件控制。 但这并没有解决SQLPlus命令(无法在PL / SQL块中执行)。

DECLARE
  lb_continue BOOLEAN;
BEGIN
  lb_continue := TRUE;
  BEGIN 

    sql statement

  EXCEPTION
    WHEN OTHERS THEN
      lb_continue = FALSE;
  END;
  IF lb_continue THEN
  BEGIN

    sql statements

  EXCEPTION
    WHEN OTHERS THEN
      lb_continue := FALSE;
  END; 
END;

当然,这种方法有其自身的局限性和问题。 任何DDL语句都需要动态调用; 最简单的方法是EXECUTE IMMEDIATE statement

最大的问题(在您的情况下)是不可能从PL / SQL块内部执行SQLPlus命令。

您无法退出脚本并保留在SQL * Plus中,但您可以停止执行。 它不漂亮,但假设您可以修改脚本以添加控制流,那么您可以使用绑定变量来执行此操作。

set serveroutput on

var flag char;
exec :flag := 'Y';

begin
    if :flag != 'Y' then
        raise program_error;
    end if;
    dbms_output.put_line('Doing some work');
    /* Check for some error condition */
    if 0 != 1 then
        raise program_error;
    end if;
    /* Only reach this if earlier statements didn't fail
     * but could wrap in another flag check if needed */
    dbms_output.put_line('Doing some more work');
    exception
        when program_error then
            dbms_output.put_line(sqlerrm);
            :flag := 'N';
        when others then
            /* Real exception handling, obviously */
            dbms_output.put_line(sqlerrm);    
            :flag := 'N';
end;
/

-- DML only does anything if flag stayed Y
select sysdate from dual
where :flag = 'Y';

-- Optional status message at the end of the script, for DBA info
set feedback off
set head off
select 'Something went wrong' from dual where :flag != 'Y';
set feedback on
set head on

执行时:

SQL> @script

PL/SQL procedure successfully completed.

Doing some work
ORA-06501: PL/SQL: program error

PL/SQL procedure successfully completed.


no rows selected


Something went wrong
SQL> 

脚本中的任何PL / SQL块都可以在开始时检查标志状态,并引发program_error (就像一个方便的预定义异常)以跳回。 PL / SQL块中的任何错误都可以直接或在异常处理程序中更新绑定变量标志。 并且任何非PL / SQL DML都可以使用额外的where子句来检查标志状态,因此如果在到达语句时将其设置为N ,则不会执行任何操作。 (对于insert我猜这意味着不使用values形式)。

这是什么不能做的是处理普通的SQL语句的任何错误,但我不知道这是一个问题。 如果是那么那些可能需要在PL / SQL块中更改为动态SQL。

我知道它的旧版本,但是在SQL脚本开头的这两条指令可以完成这项工作:

WHERVER SQLERROR EXIT FAILURE ROLLBACK

WHERVER OSERROR EXIT FAILURE ROLLBACK

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM