1

在将 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 中打印调试消息?

4

2 回答 2

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.
于 2013-02-15T23:58:34.117 回答
1

好吧,似乎 rgettman 有实际的答案,但我将把它留在这里,稍微了解一下prompt......


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

prompt Arg 1 is &1

或者你可以从 dual 中选择值,这有点混乱,或者在 a 周围有一个快速的匿名块dbms_output- 但对于这种快速检查 aprompt应该没问题。如果您只是在寻找替代值,您可以set verify on,这是默认设置,因此您的脚本目前可能将其关闭。

我似乎可以得到这种效果的唯一方法是如果我在被调用的脚本中有一个set define off(或scan off旧语法),所以它会尝试将文字字符串&1放入变量(显然不适合)而不是它的值代表。大概,从问题的第二部分,你看不到里面放了什么?

无论如何......如果这不是问题 - 如果单独调用它似乎不太可能 - 那么我想知道这是否是一个字符集问题,但这听起来也不正确。而且我还想知道为什么你要强制它是一个数值,然后将它作为一个字符串传递,这与问题并不相关。也许添加更多的 SQl 脚本可能会带来一些启示——至少从顶部到发生错误的地方。

于 2013-02-15T23:59:09.323 回答