Oracleのselect文をシェル変数に代入する方法

Oracleのselect文をシェル変数に代入する方法

うまく動作するスクリプトがありますTOAD

SELECT max (ID)+1 from apps_details;

シェルスクリプトで実行しようとすると、次のエラーが発生します。

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の出力をより簡単に処理したいと思います。あなたは努力していますシェル変数としてインポートします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_linePL/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/"$//;'
    

最良の選択は実際のユースケースによって異なります。

関連情報