如何将Oracle中的select语句分配给shell变量

如何将Oracle中的select语句分配给shell变量

我有一个运行良好的脚本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

一些替代方案:

  1. 如果您选择数字,请将其转换为字符串并在 SQL 语句中对其进行修剪。上面脚本中的其他所有内容均保持不变(SELECT为了便于测试,我将继续使用我的虚拟语句):

    SELECT TRIM(TO_CHAR(123)) FROM DUAL;
    
  2. 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),这些方法将会失败。您可以将该字符串括在引号中,然后将其删除,或者:

  1. 让 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/"$//;'
    

最佳选择取决于您的实际用例。

相关内容