引数をpsqlに渡す


10

Postgres 8.3でplpgsqlスクリプトを実行しています-psqlを介してこのスクリプトに引数を渡したいのですが。私は現在次のようなスクリプトを実行しています:

psql -d database -u user -f update_file.sql 

PGOPTIONS環境変数を説明するこのリンクに出くわしましたが、「カスタム」引数に対しては機能しません。つまり、設定がpostgres.confファイルにリストされていないため、エラーが表示されます。

-bash-3.2$ export PGOPTIONS='--pretend=true'
-bash-3.2$ psql -d my_db -f update_database.sql
psql: FATAL:  unrecognized configuration parameter "pretend"

他のアイデアは?理想的には環境変数を避けたい...


私はあなたが-vpsql の引数を探していると思います。
dezso

私はそれを試しました-スクリプトでそれを取得するために、「SELECT current_setting( 'pretend')INTO _result」を呼び出しています-成功しません。
Jmoney38

回答:


5

厳密に言うと、「plpgsqlスクリプト」などはありません。PL/ pgSQLはPostgreSQLのデフォルトの手続き型言語です。SQLスクリプトまたはplpgsql関数/プロシージャです。あなたの例はSQLスクリプトを示しているようです。

代わりに、任意の数の引数を取る(サーバー側の)plpgsql(またはsql)関数を作成できます。引数がである限り、それは非常に単純valuesです。引数に識別子が含まれている場合は、少し複雑になります。次に、動的SQLでPL / pgSQLを使用する必要があります。EXECUTEます。

PL / pgSQLは、デフォルトでPostgreSQL 9.0以降にプリインストールされています。ただし、Postgres 8.3では、データベースごとに1回インストールする必要があります。

CREATE LANGUGAGE plpgsql;

バージョンと言えば、アップグレード検討する必要があります PostgreSQLの現在のバージョンをあります。v8.3は非常に古く、2013年の初めにはサポートが終了しています。

SQLスクリプトの準備ができているようですので、SQL関数のデモを行います。2つの整数引数を持つ単純なダミー関数:

CREATE OR REPLACE FUNCTION func(int, int)
    LANGUAGE sql RETURNS void AS 
$func$
    UPDATE tbl1 SET col1 = $1 WHERE id = $2;
    UPDATE tbl2 SET col1 = $1 WHERE id = $2;
$func$;

plpgsqlのより高度な例は、dba.SEまたはSOにあります。

この関数を呼び出して、シェルスクリプトでパラメーターを渡すことができます。整数パラメーターの入力パラメーターを使用するシェルスクリプトでの呼び出しの基本的な例(値を囲む単一引用符は不要):

psql mydb -c "SELECT func($1, $2)"

または任意のデータ型:

psql mydb -c "SELECT func2('$1'::text, '$2'::numeric)"

-c1つのコマンド文字列を実行して終了します。マニュアルpsqlのコマンドライン引数の詳細。


応答をありがとう-私は実際にpgpgsqlをかなり認識しています-私が参照しているこのスクリプトは、多数の関数を含むファイルです。私はC指向プログラミングの意味で「メイン」の機能を持っています。スクリプト/ファイル内の最後の2行は、1)「メイン」関数を呼び出し、2)関数を削除しています。そのため、このセットアップでは、本質的に、実行するために実行できる自己完結型スクリプト(psql -f)を用意しています。私は、psql -cを介して「アプリケーション引数」で関数を呼び出すことについてのあなたのポイントが好きです。postgres.confファイルに値を追加するルートに行くことができないので、私はおそらくそのルートに行くでしょう。
Jmoney38

5

に別の機能を追加するには-v...引用符を追加しようとしている場合は、コマンドラインに追加します。

psql -v action="'drop'"

これにより、次のコードが実行されます。

select * where :action;

と同じ

select * where 'drop';

4

試してください-v

$ psql -U postgres -v something=\'blah-blah\'
psql (9.1.3)
Type "help" for help.

postgres=# select :something;
 ?column?
----------
 blah-blah
(1 row)

current_settingand SETまたはor を使用するsetval場合は、行postgresql.confを追加してオプションを追加する必要があります。


2

私の経験から、CREATE FUNCTION BEGINやDO BEGINなどのplpgsql宣言内でpsql変数を派生させると、構文エラーが発生します。

/tmp $ psql -U jmindek -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# select :'action';
 ?column? 
----------
 drop
(1 row)

jmindek=# DO $$ BEGIN RAISE INFO 'The value in variable action is (%)',:x; END $$;     
ERROR:  syntax error at or near ":"
LINE 1: ... RAISE INFO 'The value in variable action is (%)',:x; END $$...

私の解決策は、単一の列を持つ一時テーブルを作成し、その中に値を格納することです。この一時テーブルにはplpgsqlからアクセスできるため、DOブロックで使用されるpsql変数を渡すことができます。

 ~ $ psql -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# create temporary table actions (type text);                                                             CREATE TABLE
jmindek=# insert into actions values (:'action');                                                                 INSERT 0 1
jmindek=# do $$                                                                                                   declare                                                                                                            action_type text := null;                                                                                        begin                                                                                                               select type from actions into action_type;                                                                        raise info 'Hello, the action is (%)',action_type;                                                              end $$;
INFO:  Hello, the action is (drop)
DO
jmindek=#

CREATE FUNCTIONまたはDO宣言で追加のpsql変数を使用するには、必要な変数ごとに列を作成できます。


0

これはあまりエレガントではありませんが、動作します(疑似コード):

cat <<EOF
   UPDATE tablename SET field=$arg1 WHERE field = $arg2;
EOF | psql database

0

このアプローチは、env varsの完全な実行時解決を提供します...スクリプトが事前に設定するとすぐに、以下のすべてのシェル変数が機能します(さまざまなdbおよびホストに対して何千回も実行されています)。

    -- start run.sh

       # 01 create / modify the app user
       sql_script="$pgsql_scripts_dir/01.create-qto-app-user.pgsql"
       PGPASSWORD="${postgres_db_useradmin_pw:-}" psql -q -t -X -w -U "${postgres_db_useradmin:-}" \
          -h $postgres_db_host -p $postgres_db_port \
          -v ON_ERROR_STOP=1 \
          -v postgres_db_user_pw="${postgres_db_user_pw:-}" \
          -v postgres_db_name="${postgres_db_name:-}" \
          -f "$sql_script" "${postgres_db_name:-}" > "$tmp_log_file" 2>&1
       ret=$?
       cat "$tmp_log_file" ; cat "$tmp_log_file" >> $log_file # show it and save it
       test $ret -ne 0 && sleep 3
       test $ret -ne 0 && doExit 1 "pid: $$ psql ret $ret - failed to run sql_script: $sql_script !!!"
    -- stop run.sh

    -- start fun.sql
            DO
            $do$
            BEGIN
               IF NOT EXISTS (
                  SELECT
                  FROM   pg_catalog.pg_roles
                  WHERE  rolname = 'usrqtoapp') THEN
                     CREATE ROLE usrqtoapp WITH PASSWORD ':postgres_db_user_pw' LOGIN ;
               END IF;
            END
            $do$;
            ALTER ROLE usrqtoapp WITH PASSWORD  :'postgres_db_user_pw' LOGIN ;

    -- eof run.sql
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.