sqlplus直接传入连接字符串变量连接Oracle失败问题求助
问题背景
现有Oracle数据库连接字符串变量SQLSTR,执行echo输出内容如下:
echo $SQLSTR sys/<pwd>@(DESCRIPTION=(ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=xxxx)(INSTANCE_NAME=xxxx))) AS SYSDBA"
通过sqlplus的nolog模式配合EOF交互块写入connect命令的方式可以正常连接,可用代码如下:
sqlplus -s /nolog << EOF WHENEVER SQLERROR EXIT 99 connect ${SQLSTR} EOF
尝试将连接参数直接写在sqlplus启动命令行、不放入EOF交互块时始终连接失败,测试的两种错误写法如下:
# 第一种错误写法 sqlplus "${SQLSTR}" > $log << EOF WHENEVER SQLERROR EXIT ROLLBACK .... EOF # 第二种错误写法 SQLSTR2="\"$SQLSTR\"" sqlplus "${SQLSTR2}" > $log << EOF WHENEVER SQLERROR EXIT ROLLBACK .... EOF
故障原因
两种写法失败的核心原因有两点:
- 从echo输出的结果看,
SQLSTR变量末尾自带了一个冗余的双引号,属于赋值时遗留的非法字符,会直接导致连接参数解析失败。 - 命令行传参时,shell会对空格、括号这类特殊字符做参数拆分,直接传
"${SQLSTR}"时,shell会把连接串拆成多个独立参数传给sqlplus,sqlplus无法拿到完整的连接信息;第二种手动加转义引号的写法,又因为调用时额外套了一层双引号,导致传给sqlplus的字符串首尾多了无意义的引号字符,参数格式不符合要求。
而EOF交互块内写connect命令能成功,是因为here-doc内的变量替换完成后,内容直接输入到sqlplus的交互流,不会经过shell的命令行参数拆分逻辑,特殊字符、空格都能完整传递给sqlplus。
修复方案
第一步:先清理变量内的冗余字符
首先移除SQLSTR末尾多余的双引号:
SQLSTR=${SQLSTR%\"}
第二步:选择对应可用的调用写法
写法1:调用时直接转义传参
不需要提前构造新变量,调用sqlplus时给连接串加转义双引号,让shell把完整的带引号连接串传给sqlplus即可:
sqlplus \"${SQLSTR}\" > $log << EOF WHENEVER SQLERROR EXIT ROLLBACK .... EOF
写法2:提前构造好连接参数
提前拼接好sqlplus可识别的带引号连接串,调用时直接传变量,注意不要给变量额外加外层双引号:
# 提前拼接符合sqlplus格式要求的连接串 SQLSTR_FULL="\"${SQLSTR}\"" # 直接传参调用,不要加外层引号 sqlplus ${SQLSTR_FULL} > $log << EOF WHENEVER SQLERROR EXIT ROLLBACK .... EOF
注意:sqlplus命令行接收包含空格、特殊字符的连接串时,要求整个连接串必须用双引号包裹,否则会把空格后的内容(比如
AS SYSDBA)识别为独立启动参数,而非连接串的一部分。
内容的提问来源于stack exchange,提问作者jiii
相关产品推荐
相关产品推荐

