如何处理调用 sqlplus 的批处理文件中的错误,因为 sqlplus 没有在错误或失败时设置 ERRORLEVEL?

Posted

技术标签:

【中文标题】如何处理调用 sqlplus 的批处理文件中的错误,因为 sqlplus 没有在错误或失败时设置 ERRORLEVEL?【英文标题】:How do I handle errors in a batch file that calls sqlplus, because sqlplus doesn't set ERRRORLEVEL on error or failure? 【发布时间】:2011-12-02 01:20:16 【问题描述】:

我在这里遇到了一个问题,我已经花了几天时间来解决它..

我的解释会很长,但我尽量保持简短。

在我的 Oracle SQLdeveloper 中,我有一个包名 UT_BETWNSTR,其中包含:

create or replace
PACKAGE "UT_BETWNSTR" 
IS
PROCEDURE ut_setup;
PROCEDURE ut_teardown;

PROCEDURE ut_betwnstr;
END UT_BETWNSTR;

包体是这样的:

    create or replace
PACKAGE BODY      "UT_BETWNSTR" 
IS
   PROCEDURE ut_setup IS
   BEGIN
      NULL;
   END;

   PROCEDURE ut_teardown
   IS
   BEGIN
      NULL;
   END;

   PROCEDURE ut_BETWNSTR IS
      BEGIN
       utAssert.eq (
            'Typical valid usage',
             BETWNSTR(
             STRING_IN => 'abcdefg',
             START_IN => 3,
            END_IN => 5)
           ,
         'abc'
         );
         utAssert.isnull (
           'NULL start',
             BETWNSTR(
             STRING_IN => 'abcdefg',
             START_IN => NULL,
             END_IN => 5)
           );
           utAssert.isnull (
              'NULL end',
            BETWNSTR(
            STRING_IN => 'abcdefg',
            START_IN => 2,
             END_IN => NULL)
           );
           utAssert.isnull (
                  'End smaller than start',
                   BETWNSTR(
                   STRING_IN => 'abcdefg',
                   START_IN => 5,
                   END_IN => 2)
          );
          utAssert.eq (
                  'End larger than string length',
                   BETWNSTR(
                   STRING_IN => 'abcdefg',
                   START_IN => 3,
                   END_IN => 200)
           ,
         'cdefg'
         );

           END ut_betwnstr;

END UT_BETWNSTR;

而函数名BETWNSTR是这样的:

create or replace
FUNCTION BETWNSTR (
   string_in   IN   VARCHAR2,
   start_in    IN   INTEGER,
   end_in      IN   INTEGER
)
   RETURN VARCHAR2
IS
   l_start PLS_INTEGER := start_in;
BEGIN
   IF l_start = 0
   THEN
      l_start := 1;
   END IF;

   RETURN (SUBSTR (string_in, l_start, end_in - l_start + 1));
END;

在我的 C 盘中,我放了一个文件名 BETWNSTR.sql,其中包含:

connect hr/hr
SET SERVEROUTPUT ON
EXEC UTPLSQL.TEST('BETWNSTR',Recompile_in=>FALSE);
exit

这是我的批处理文件(也在 C 盘中),名称为 try.bat,其中包含:

@sqlplus /nolog @C:\betwnstr.sql

echo %errorlevel%
if errorlevel 0 goto Success
echo You Got Error

:Success
echo Good Job!!

pause

好的,错误来了

当我运行 try.bat 时,它会返回我故意放的大 FAILURE 结果

PROCEDURE ut_BETWNSTR IS
  BEGIN
   utAssert.eq (
        'Typical valid usage',
         BETWNSTR(
         STRING_IN => 'abcdefg',
         START_IN => 3,
        END_IN => 5)
       ,
     'abc'
     );

而不是

PROCEDURE ut_BETWNSTR IS
  BEGIN
   utAssert.eq (
        'Typical valid usage',
         BETWNSTR(
         STRING_IN => 'abcdefg',
         START_IN => 3,
        END_IN => 5)
       ,
     'cde'
     );

我这样做是故意的,所以我希望 cmd 会回显:

You Got Error

因为我的代码中有错误..但是错误级别正在回显 0,这意味着它是成功的..

我知道,我的代码现在取决于 errorlevel..当 errorlevel 为 0 时,它会回显 Good Job..

我现在想要的是,当我运行批处理文件时,当它遇到错误时,我可以回显 You Got Error 消息..

当错误级别始终显示为 0 时,我如何回显“您遇到错误”消息..

简而言之,我想在不依赖错误级别的情况下回显错误消息..

我希望任何解决我问题的人都可以回答我的问题..

提前致谢!

【问题讨论】:

所以你的实际问题是“如何处理调用 sqlplus 的批处理文件中的错误,因为 sqlplus 没有在错误或失败时设置 ERRRORLEVEL?” 感谢您的评论,@KenWhite 【参考方案1】:

所有之前的答案都回答了:“如何处理调用 sqlplus 的批处理文件中的错误, sqlplus 没有在错误或失败时设置 ERRRORLEVEL?”

但您实际上可以使用以下 sqlplus 命令以非零退出代码使 sqlplus 在错误时退出:

whenever sqlerror exit sql.sqlcode

另见http://voidtech.wordpress.com/2013/03/06/execute-an-script-with-sqlplus-and-get-the-exitcode-to-the-environment/ 我在装有Oracle 10g 的windows 机器上以这种方式使用它:

sqlplus some_user/pw@tns_name @ some_script.sql
IF %ERRORLEVEL% NEQ 0 call some_action_on_error.vbs

【讨论】:

【参考方案2】:

我不确定这是否可行,但也许值得一试。 (我没有 Windows 机器,所以无法测试,但看起来差不多)这将取决于 sql 写入标准输出的能力。我不了解 Oracle,所以我不知道你是否可以让它做到这一点,但如果可以的话,如果你知道错误/警告消息的标准模式,下面的小技巧应该可以工作。如果 /nolog 停止打印到标准输出,请将其从下面的 sn-p 中取出。值得一试。祝你好运! :)

setlocal enabledelayedexpansion

some_text_signifying_error=whatever you can get sql to display to Standard Output
set msg=''

For 'eol=; tokens=1 delims=' %%e in ('@sqlplus /nolog @C:\betwnstr.sql ^| findstr /i /c:"!some_text_signifying_error!"') do (
    set msg=!msg! %%e
)

if NOT !msg!='' echo !msg!

【讨论】:

查看以下链接的第一个响应,它使用了我建议的相同方法,并添加了一些额外的 sqlplus 内容来帮助您填补空白...dbforums.com/oracle/1044496-sqlplus-return-value-help.html 看起来你的回答对我有很大帮助..现在我正在尝试消化它..我让你知道它是否成功.. 我很高兴听到它在某种程度上有所帮助。我希望我能提供更多帮助,但我的预言机经验为 0 >. 好的,现在我可以发现我的代码失败了! =D 我正在使用 For /F .. 如果它检测到失败,我可以知道如何回显,它会回显 You Got Prob,如果它没有检测到任何故障,它将返回无 ..在此之前我取决于错误级别回显errorMessage..现在我不再依赖于错误级别,这就是为什么我在这里有点困惑..谢谢! 好的,这是我目前的代码: setlocal enabledelayedexpansion For /F "tokens=* delims= " %%e in ('@sqlplus /nolog @C:\btwn.sql ^| findstr / i /c:"FAILURE"') 做 ( set msg=!msg! %%e ) PAUSE

以上是关于如何处理调用 sqlplus 的批处理文件中的错误,因为 sqlplus 没有在错误或失败时设置 ERRORLEVEL?的主要内容,如果未能解决你的问题,请参考以下文章

使用app.get调用错误端点时如何处理?

你如何处理来自 AJAX 调用的错误?

如何处理nodejs中的数组缓冲区分配失败?

如何处理返回 PartialView 的 ajax 调用控制器操作中的模型状态错误

处理 Mongoose 验证错误——在哪里以及如何处理?

处理包/模块中的错误时如何处理Python异常