从shell传递到sqlplus时可变长度的变化

时间:2013-02-15 18:09:46

标签: sql oracle shell unix sqlplus

在将1个字符变量从sqlplus传递给shell时,我发现这个令人讨厌的异常现象。

echo "Please enter the upgrade option: "
read type

if [[ "$type" != "1" ]] && [[ "$type" != "2" ]]
then
            echo "You have entered an invalid response. Exiting."
    exit 0;
fi

sql_result=$($ORACLE_HOME/bin/sqlplus -s /nolog <<-EOF
connect $eval_user/$eval_pass@$db_name

SPOOL results.txt;
WHENEVER OSERROR EXIT 9;

DEFINE vType = '$type'
DEFINE type_flag = '$t_flag'
DEFINE vOrigowner = '$origOwner'
@@EV_DBUPGRADE.sql '&vType' '&vOrigowner' '&vAppConvFromDt' '&vAppConvThruDt' '&vAppConvStatusFlg' '&type_flag'

在EV_DBUPGRADE.sql下,我在使用变量vType时发现此错误:

vOption        varchar2(1)  := UPPER('&1');

我得到这个令人讨厌的错误,抱怨缓冲区长度

declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 7

如果使用varchar2(10),则不会发生错误。但是,我不想在百万个不同的地方改变它。反正有限制吗?谁能告诉我如何在BEGIN之外的sqlplus中打印调试消息?

2 个答案:

答案 0 :(得分:2)

我不确定这里到底发生了什么,但shell正在为你的shell变量做些什么。

我能够在ksh(“testme.ksh”)

中复制你的错误
#!/bin/ksh

type="1"

sqlresult=$($ORACLE_HOME/bin/sqlplus -s /nolog << EOF
connect user/pswd@database
define vType = '$type'
@test.sql &vType
exit
/
EOF)

echo $sqlresult

SQL脚本(“test.sql”):

declare
   vOption varchar2(1) := UPPER('&1');
begin
   dbms_output.put_line('Test: ' || vOption);
end;
/

输出:

Connected. old 2: vOption varchar2(1) := UPPER('&1'); new 2: vOption varchar2(1)
:= UPPER('$type'); declare test.sql testme.ksh ERROR at line 1: ORA-06502: PL/SQ
L: numeric or value error: character string buffer too small ORA-06512: at line
2

我不确定为什么会这样,但我能够通过将shell变量直接传递给SQL脚本执行并绕过“define”语句来解决它:

#!/bin/ksh

type="1"

sqlresult=$($ORACLE_HOME/bin/sqlplus -s /nolog << EOF
connect user/pswd@database
@test.sql $type
exit
/
EOF)

echo $sqlresult

输出:

Connected. old 2: vOption varchar2(1) := UPPER('&1'); new 2: vOption varchar2(1)
:= UPPER('1'); PL/SQL procedure successfully completed.

答案 1 :(得分:1)

好吧,似乎rgettman有实际的答案,但我会留下这里关于prompt ...


添加调试的快速版本是使用提示符:

prompt Arg 1 is &1

或者您可以从双重中选择值,这有点麻烦,或者在dbms_output周围快速匿名阻止 - 但是对于这种快速检查,prompt应该没问题。如果你只是在寻找替代值,你可以set verify on,这是默认值,所以你的脚本可能暂时关闭它。

我似乎能够获得这种效果的唯一方法是,如果我在被调用脚本中有set define off(或scan off旧语法),那么它会尝试放置文字字符串{{1变量(显然不适合)而不是它代表的值。据推测,从问题的第二部分来看,你看不出那里放的是什么?

无论如何......如果这不是问题 - 而且如果它被隔离调用似乎不太可能 - 那么我想知道它是否是一个字符集问题,但这听起来也不对。而且我也想知道为什么你强迫它成为一个数值,然后将它作为一个字符串传递,这与问题无关。也许添加更多的SQl脚本可能会有所启发 - 至少从顶部到发生错误的位置。