我有一个运行良好的脚本TOAD
:
SELECT max (ID)+1 from apps_details;
当我尝试在 shell 脚本中运行它时,出现错误:
DB_CONNECT="XXXXX/XXXXX@XXXXXX"
echo "Inserting the DataBase"
/oravl01/oracle/12.1.0.1/bin/sqlplus -s $DB_CONNECT <<END
set head off
set feedback off
set pagesize 2400
set linesize 2048
ID_VAL=`SELECT max (ID)+1 from apps_details;`
exit
END
/pciuser/tools/jenkins/jenkins/scripts/Jenkins_Internal/Create_Jenkins_Container/InsertToDB.ksh[31]: syntax error at line 1: `(' unexpected
31号线指的是oravl01
行,但我知道问题不存在,因为一旦我删除了ID_VAL
作业,它就起作用了。
正确的语法是什么?
答案1
这些命令对我有用:
DB_CONNECT="XXXXX/XXXXX@XXXXX"
ID_VAL=$(sqlplus -s $DB_CONNECT <<END
set head off
set feedback off
set pagesize 2400
set linesize 2048
SELECT max (ID)+1 from apps_details;
exit;
END
)
echo $ID_VAL
答案2
我认为首先定义命令然后运行它以保存其输出会更干净(也更简单):
DB_CONNECT="XXXXX/XXXXX@XXXXXX"
read -r -d '' command <<END
set head off
set feedback off
set pagesize 2400
set linesize 2048
SELECT max (ID)+1 from apps_details;
exit
END
echo "Inserting the DataBase"
ID_VAL=$(/oravl01/oracle/12.1.0.1/bin/sqlplus -s "$DB_CONNECT" <<<"$command")
这样,您可以轻松地将输出存储在变量中,并且将命令与脚本流程分开,这将使将来更容易理解和维护。
答案3
这里有一些替代方案,大致如下特登的回答,尝试让处理 SQL*Plus 的输出变得更容易你在尝试将其获取到 shell 变量中ID_VAL
。
默认情况下,在 SQL*Plus 中执行的 SQL 语句会生成格式化报告,该报告由宽度取决于各自数据类型的列组成。这将导致一些可能不需要的效果:例如,您指出的左侧填充的数字在评论中。
示范:
$ DB_CONNECT="user/password@db"
$ ID_VAL="$(sqlplus -s $DB_CONNECT <<'END'
set feedback off
set head off
set pagesize 0
SELECT 123 FROM DUAL
/
END
)"
$ printf '"%s"\n' "$ID_VAL"
" 123"
$ printf '%s' "$ID_VAL" | od -An -tx1
20 20 20 20 20 20 20 31 32 33
一些替代方案:
如果您选择数字,请将其转换为字符串并在 SQL 语句中对其进行修剪。上面脚本中的其他所有内容均保持不变(
SELECT
为了便于测试,我将继续使用我的虚拟语句):SELECT TRIM(TO_CHAR(123)) FROM DUAL;
dbms_output.put_line
在 PL/SQL 块中使用:ID_VAL="$(sqlplus -s $DB_CONNECT <<'END' set serveroutput on set feedback off DECLARE myvar NUMBER; BEGIN SELECT 123 INTO myvar FROM DUAL; dbms_output.put_line(myvar); END; / END )"
请注意,这
set serveroutput on
是必需的,否则不会显示任何输出。
结合(1)和(2),您将得到:
$ printf '"%s"\n' "$ID_VAL"
"123"
$ printf '%s' "$ID_VAL" | od -An -tx1
31 32 33
但请注意,如果您选择的字符串带有要保留的侧翼空白字符(例如foo
),这些方法将会失败。您可以将该字符串括在引号中,然后将其删除,或者:
让 SQL*Plus 将其输出格式化为 CSV:
ID_VAL="$(sqlplus -s -M "CSV ON" $DB_CONNECT <<'END' set feedback off set head off SELECT ' foo ' FROM DUAL; END )" printf '"%s"\n' "$ID_VAL" "" foo ""
与数字不同,字符串将被双引号括起来,需要一些后处理。假设返回的值不包含
<newline>
字符,一种方法可能是使用sed
删除开始和结束"
字符(其他一切不变):ID_VAL="$(sqlplus -s -M "CSV ON" $DB_CONNECT <<'END' | sed 's/^"//; s/"$//;'
最佳选择取决于您的实际用例。