来自 Bash 的 SQLPlus 错误处理 - 不工作
Error Handling of SQLPlus from Bash - not working
我已经阅读了关于这个问题的所有相关 link 和类似的 questions/answers,preveland 答案是首先设置 whenever SQLERROR EXIT SQL.SQLCODE;
然后才进行查询,然后检查 SQL Plus return 代码使用:ERRORCODE=$?
这是一个示例脚本:
GetAmountOfChunks()
{
export CHUNK_AMOUNT=`sqlplus -s $CONSTR<<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT SQL.SQLCODE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
/
SQL`
当运行处于调试模式时,它给出:
++ sqlplus -s USER/PASS@HOST/DB
+ export 'CHUNK_AMOUNT= select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ CHUNK_AMOUNT=' select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ ERRORCODE=0
+ '[' 0 -ne 0 ']'
如您所见,returned 代码为 0!
我预计如果不是 1476,则至少为 196(最右边的 8 个字节),但不是 0,表示成功!
请帮忙...
谢谢。
您的 ERRORCODE
被设置为零,因为那是子程序的退出代码shell 您正在 运行ning SQL*此外,viq 反引号. SQL*Plus 进程的退出代码是 196,但您没有捕获它,并且在 heredoc 中做到这一点并不容易。来自进程的标准输出——这是你正在捕获的——不是那个退出代码,它是正在打印的查询和错误消息。即使您可以捕获它,我也不确定您如何区分 196 是来自错误还是来自您的实际查询。
您可以执行类似 运行 在隐藏错误并打印默认值或实际计算值的块中执行查询,或者只查看输出的最后一行并尝试解释那;但你仍然会反对它显示命令是 运行。 SQL*Plus 有 set echo off
但它对交互式会话没有任何作用,这仍然与输入重定向有关。
另一种方法是创建脚本文件并临时存储输出:
echo "
set pages 0
set trim on
set feed off
set echo off
whenever SQLERROR EXIT FAILURE
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0;
" > /tmp/GetAmountOfChunks_$$.sql
sqlplus -s -l $CONSTR @/tmp/GetAmountOfChunks_$$.sql > /tmp/GetAmountOfChunks_$$.out
if [[ $? -eq 0 ]]; then
export CHUNK_AMOUNT=`cat /tmp/GetAmountOfChunks_$$.out`
else
# whatever you want to do on error; show output file? set default?
cat /tmp/GetAmountOfChunks_$$.out
fi
rm -f /tmp/GetAmountOfChunks_$$.sql /tmp/GetAmountOfChunks_$$.out
这会创建一个(特定于进程的).sql 文件;执行将输出(减去语句,通过 set echo off
)写入 .out 文件;检查 SQL*Plus 退出代码;如果该值为零,则从文件中获取结果。
正如您暗示的那样,依靠 SQL.SQLCODE
来检测 shell 脚本中的错误是危险的,因为您可能会得到一个回绕为零的错误,所以我使用了通用的 FAILURE
.如果您需要真正的错误代码,您可以从输出文件中获取它。
另一种使用 PL/SQL 块的方法:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
set serveroutput on;
declare
chunk_amount number;
begin
select 1/0 into chunk_amount from dual;
--SELECT COUNT(*) INTO chunk_amount FROM CNV_CHUNKS_PROC_STATUS;
dbms_output.put_line(chunk_amount);
exception
when others then
dbms_output.put_line(sqlcode);
end;
/
exit 0
SQL
exit $?`
ERRORCODE=$?
如果 PL/SQL 块 运行 则 ERRORCODE
将为零,如果成功则 CHUNK_AMOUNT
将是计算值,或者 SQL抛出异常时的代码;因为这将是负数(在您的示例中为 -1476),如果您只期望正值,您可以测试它是否符合预期。
如果该块由于语法错误或凭据无效而无法 运行(请注意我偷偷插入的 -l
标志),那么 ERRORCODE
将为 1 并且 CHUNK_AMOUNT
将有错误文本,例如ERROR: ORA-12154: TNS:could not resolve the connect identifier...
或任何实际出错的地方。 set -f
停止错误消息中的 *
从当前目录扩展到文件列表。
或者更简单、更接近您的原作:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0
SQL
exit $?`
ERRORCODE=$?
现在ERRORCODE
成功是0,CHUNK_AMOUNT
任何错误的计算值ERRORCODE
是1,你可以直接测试,实际错误总是在CHUNK_AMOUNT
- 但仅作为字符串,您不会以这种方式获得 -1476。
我已经阅读了关于这个问题的所有相关 link 和类似的 questions/answers,preveland 答案是首先设置 whenever SQLERROR EXIT SQL.SQLCODE;
然后才进行查询,然后检查 SQL Plus return 代码使用:ERRORCODE=$?
这是一个示例脚本:
GetAmountOfChunks()
{
export CHUNK_AMOUNT=`sqlplus -s $CONSTR<<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT SQL.SQLCODE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
/
SQL`
当运行处于调试模式时,它给出:
++ sqlplus -s USER/PASS@HOST/DB
+ export 'CHUNK_AMOUNT= select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ CHUNK_AMOUNT=' select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero'
+ ERRORCODE=0
+ '[' 0 -ne 0 ']'
如您所见,returned 代码为 0! 我预计如果不是 1476,则至少为 196(最右边的 8 个字节),但不是 0,表示成功!
请帮忙...
谢谢。
您的 ERRORCODE
被设置为零,因为那是子程序的退出代码shell 您正在 运行ning SQL*此外,viq 反引号. SQL*Plus 进程的退出代码是 196,但您没有捕获它,并且在 heredoc 中做到这一点并不容易。来自进程的标准输出——这是你正在捕获的——不是那个退出代码,它是正在打印的查询和错误消息。即使您可以捕获它,我也不确定您如何区分 196 是来自错误还是来自您的实际查询。
您可以执行类似 运行 在隐藏错误并打印默认值或实际计算值的块中执行查询,或者只查看输出的最后一行并尝试解释那;但你仍然会反对它显示命令是 运行。 SQL*Plus 有 set echo off
但它对交互式会话没有任何作用,这仍然与输入重定向有关。
另一种方法是创建脚本文件并临时存储输出:
echo "
set pages 0
set trim on
set feed off
set echo off
whenever SQLERROR EXIT FAILURE
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0;
" > /tmp/GetAmountOfChunks_$$.sql
sqlplus -s -l $CONSTR @/tmp/GetAmountOfChunks_$$.sql > /tmp/GetAmountOfChunks_$$.out
if [[ $? -eq 0 ]]; then
export CHUNK_AMOUNT=`cat /tmp/GetAmountOfChunks_$$.out`
else
# whatever you want to do on error; show output file? set default?
cat /tmp/GetAmountOfChunks_$$.out
fi
rm -f /tmp/GetAmountOfChunks_$$.sql /tmp/GetAmountOfChunks_$$.out
这会创建一个(特定于进程的).sql 文件;执行将输出(减去语句,通过 set echo off
)写入 .out 文件;检查 SQL*Plus 退出代码;如果该值为零,则从文件中获取结果。
正如您暗示的那样,依靠 SQL.SQLCODE
来检测 shell 脚本中的错误是危险的,因为您可能会得到一个回绕为零的错误,所以我使用了通用的 FAILURE
.如果您需要真正的错误代码,您可以从输出文件中获取它。
另一种使用 PL/SQL 块的方法:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
set serveroutput on;
declare
chunk_amount number;
begin
select 1/0 into chunk_amount from dual;
--SELECT COUNT(*) INTO chunk_amount FROM CNV_CHUNKS_PROC_STATUS;
dbms_output.put_line(chunk_amount);
exception
when others then
dbms_output.put_line(sqlcode);
end;
/
exit 0
SQL
exit $?`
ERRORCODE=$?
如果 PL/SQL 块 运行 则 ERRORCODE
将为零,如果成功则 CHUNK_AMOUNT
将是计算值,或者 SQL抛出异常时的代码;因为这将是负数(在您的示例中为 -1476),如果您只期望正值,您可以测试它是否符合预期。
如果该块由于语法错误或凭据无效而无法 运行(请注意我偷偷插入的 -l
标志),那么 ERRORCODE
将为 1 并且 CHUNK_AMOUNT
将有错误文本,例如ERROR: ORA-12154: TNS:could not resolve the connect identifier...
或任何实际出错的地方。 set -f
停止错误消息中的 *
从当前目录扩展到文件列表。
或者更简单、更接近您的原作:
set -f
CHUNK_AMOUNT=`sqlplus -s $CONSTR <<SQL
set heading off;
set trim on;
set feed off;
whenever SQLERROR EXIT FAILURE;
select 1/0 from dual;
--SELECT COUNT(*) FROM CNV_CHUNKS_PROC_STATUS;
exit 0
SQL
exit $?`
ERRORCODE=$?
现在ERRORCODE
成功是0,CHUNK_AMOUNT
任何错误的计算值ERRORCODE
是1,你可以直接测试,实际错误总是在CHUNK_AMOUNT
- 但仅作为字符串,您不会以这种方式获得 -1476。