【问题标题】:how to handle sql script from unix如何处理来自unix的sql脚本
【发布时间】:2015-01-03 05:47:42
【问题描述】:

我实际上是使用下面的代码从 Unix 调用 SQL 脚本。 SQL 脚本有数百万个将在我的数据库上运行的 DML。要求是,如果 DML 失败,则脚本应该使用退出代码中止,而不是跳到下一个 DML。目前,它正在执行所有 DML,而不会在失败的 DML 处中断。我们实际上需要对脚本进行更多控制。我们怎样才能做到这一点?请帮忙。

脚本正文

#! /bin/sh

    echo "Script started at `date`"

    #************** Execute the extract sql on Staging database***************#
    `sqlplus -s $CCBSTGID/$CCBSTGPASSWRD@$CCBSTGDBASE <<EOF
    whenever sqlerror exit 2;
    whenever error exit 3;
    set termout on
    set echo on
    set serveroutput on
    set pagesize 0
    set linesize 500
    set heading off
    set verify on
    set feedback on

    spool output1.txt;
    @DMLFile.sql
    spool off;
    quit;

    EOF`

    RC=$?

    echo $RC

    if [ ${RC} != 0 ]
    then
    echo "Script execution failed"
    exit 1
    fi

【问题讨论】:

  • 您是否真的打算用反引号包围 sqlplus &lt;EOF ... EOF 块,或者您只是不确定 S.O.格式化?如前所述,反引号没有任何价值。
  • 您能解释一下@DMLFile.sql 里面的内容吗?事物的结构如何?

标签: oracle unix sqlplus


【解决方案1】:

问题在于您没有将 DML 语句包装在 PL/SQL 块中,因此 WHENEVER SQLERROR ... 没有像您期望的那样工作。这是一个演示该问题的测试用例。

-- File: dmlfile.sql
update a set name = 'A';
foo; -- erroneous command to cause error
update a set name = 'B';

之前...

C:\>perl wrapper.pl

1 row updated.

SP2-0042: unknown command "foo" - rest of line ignored.

1 row updated.

糟糕,两个更新语句都执行了;错误后脚本没有退出。

用 BEGIN 和 END 包装后

-- File: dmlfile.sql
begin
    update a set name = 'A';
    foo; -- erroneous command to cause error
    update a set name = 'B';
end;
/

运行它:

C:\>perl wrapper.pl
        foo; -- erroneous command to cause error
        *
ERROR at line 3:
ORA-06550: line 3, column 2:
PLS-00201: identifier 'FOO' must be declared
ORA-06550: line 3, column 2:
PL/SQL: Statement ignored

另外,我不知道任何命令WHENEVER ERROR,也许你在想WHENEVER OSERROR

查看上一个答案:PL/SQL: is there an instruction to completely stop the script execution?

尝试将所有 DML 包装在 BEGIN ... END 块中:

-- DMLFile.sql
BEGIN
    -- your DML statements here
END;
/

或将每个单独的逻辑语句块包装在一个块中。

-- DMLFile.sql
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK;

BEGIN
    -- block 1
END;
/

BEGIN
    -- block 2
END;
/

WHENEVER SQLERROR EXIT 是一个 SQLPlus 指令,不是标准 SQL,但具有相当的可移植性;它适用于 SQLPlus、SQL Developer、Toad、PL/SQL Developer、SQLsmith 等。

另一种方法是在您的 DML 周围使用其他一些 GUI 客户端,或者将整个脚本传递给可以执行批处理模式的工具。 Toad 将在出现一个错误后停止并提示您。

【讨论】:

  • 原帖不是已经包含whenever sqlerror了吗?你是说最好让每个@dml1.sql 文件都是自包含的,带有PL/SQL 陷阱和whenever sqlerror,然后从脚本中调用sqlplus scott/tiger @dml1.sql?谢谢,有趣的帖子!
  • @shelter - 当我第一次阅读他的帖子时,我以为他有“数百万”个 DML 脚本,但它们都失败了,但似乎他有一个巨大的脚本,实际上我错过了这个事实他已经有whenever sqlerror。我必须重新考虑我的答案!
  • 修改了我的答案。问题是他的 DML 必须是一堆单独的 SQL 语句,而不是 BEGIN/END 块。如果他使用 BEGIN/END 块,那么 WHENEVER SQLERROR 指令将起作用。
  • 太好了,感谢您的修改。我在工作中已经处理了一点,但还不足以通过听说来了解,而且我今天无法访问。祝大家好运!
【解决方案2】:

SQLPLUS 无法解析该命令,因此它从未将其转换为 SQL。 SP2-0042 错误是一个 sqlplus 错误,因此它不会被 WHENEVER SQLERROR EXIT 指令捕获。可悲的是,没有等效的 SQLPLUSERROR 指令....

但是,从 11g sqlplus(不是数据库)开始,Oracle 提供了一个错误日志工具,可以用来捕获各种错误。

SQLPLUS&gt; set errorlogging on

我终于在这里找到了参考:SQLPlus User Guide

【讨论】:

    猜你喜欢
    • 2018-12-13
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    相关资源
    最近更新 更多