您的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,您可以直接测试,实际错误始终在 CHUNK_AMOUNT - 但仅作为字符串,这样你不会得到 -1476。