我有一些经常运行的脚本,总是来自连接的SQLPlus会话。
我需要一种方法在发生错误时退出脚本,没有断开连接或退出SQLPlus本身。 100%的情况下,当发生错误时,连接的DBA将需要向会话发出一个或多个命令。 100%的时间,当发生错误时,脚本中有其他SQLPlus语句(因此必须 }) 不得执行或可能出现严重问题。
注意:如果您建议BEGIN..END;
,那么您没有阅读上述文字。除了脚本之外,这将断开并退出SQLPlus ,这是不可接受的行为。
答案 0 :(得分:8)
我发现了一个有趣的想法here,当它与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
答案 1 :(得分:4)
这是不可能的。
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命令。
答案 2 :(得分:1)
您无法退出脚本并保留在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。
答案 3 :(得分:-1)
我知道它的旧版本,但是在SQL脚本开头的这两条指令完成了工作:
WHERVER SQLERROR EXIT FAILURE ROLLBACK
WHERVER OSERROR EXIT FAILURE ROLLBACK