我已阅读有关此问题的所有相关链接以及类似问题/答案,preveland回答是先设置whenever SQLERROR EXIT SQL.SQLCODE;
然后才进行查询,然后使用: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 ']'
如您所见,返回的代码为0! 我预计如果不是1476,那么至少196(最多8个字节),但不是0表示成功!
请帮忙......
感谢。
答案 0 :(得分:2)
您的ERRORCODE
被设置为零,因为您正在运行SQL * Plus的子shell中的退出代码是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,您可以直接测试,实际错误始终为{{ 1}} - 但只是作为字符串,你不能以这种方式获得-1476。