163

MS SQL Server で、カスタマイズ可能な変数を使用するスクリプトを作成します。

DECLARE @somevariable int  
SELECT @somevariable = -1

INSERT INTO foo VALUES ( @somevariable )

@somevariable次に、特定の状況で必要な値に応じて、実行時にの値を変更します。スクリプトの先頭にあるので、見やすく覚えやすいです。

PostgreSQL クライアントで同じことを行うにはどうすればよいpsqlですか?

4

13 に答える 13

204

Postgres 変数は \set コマンドで作成されます。たとえば ...

\set myvariable value

...そして、たとえば...のように置き換えることができます

SELECT * FROM :myvariable.table1;

... また ...

SELECT * FROM table1 WHERE :myvariable IS NULL;

編集: psql 9.1 以降、変数は次のように引用符で囲むことができます。

\set myvariable value 

SELECT * FROM table1 WHERE column1 = :'myvariable';

古いバージョンの psql クライアントでは:

... 次のような条件付き文字列クエリの値として変数を使用する場合 ...

SELECT * FROM table1 WHERE column1 = ':myvariable';

...次に、上記が機能しないため、変数自体に引用符を含める必要があります。代わりに、変数をそのように定義してください...

\set myvariable 'value'

ただし、私のように、既存の変数から文字列を作成したい状況に遭遇した場合、トリックはこれであることがわかりました...

\set quoted_myvariable '\'' :myvariable '\''

これで、同じ文字列の引用符付き変数と引用符なし変数の両方ができました! そして、あなたはこのようなことができます....

INSERT INTO :myvariable.table1 SELECT * FROM table2 WHERE column1 = :quoted_myvariable;
于 2010-08-27T23:40:58.287 に答える
69

PSQL 変数に関する最後の言葉:

  1. SQL ステートメントで単一引用符で囲むと、展開されません。したがって、これは機能しません:

    SELECT * FROM foo WHERE bar = ':myvariable'
    
  2. SQL ステートメントで文字列リテラルに展開するには、変数セットに引用符を含める必要があります。ただし、変数値はすでに引用符で囲む必要があります。つまり、2 番目の引用符セットが必要であり、内側のセットをエスケープする必要があります。したがって、次のものが必要です。

    \set myvariable '\'somestring\''  
    SELECT * FROM foo WHERE bar = :myvariable
    

    EDIT : PostgreSQL 9.1 以降では、代わりに次のように記述できます。

    \set myvariable somestring
    SELECT * FROM foo WHERE bar = :'myvariable'
    
于 2008-08-31T17:36:49.853 に答える
61

WITH句を使用してみることができます。

WITH vars AS (SELECT 42 AS answer, 3.14 AS appr_pi)
SELECT t.*, vars.answer, t.radius*vars.appr_pi
FROM table AS t, vars;
于 2013-03-08T14:26:13.540 に答える
38

特に の場合、コマンド ラインからも変数をpsql渡すことができます。psqlで渡すことができます-v。使用例を次に示します。

$ psql -v filepath=/path/to/my/directory/mydatafile.data regress
regress=> SELECT :'filepath';
               ?column?                
---------------------------------------
 /path/to/my/directory/mydatafile.data
(1 row)

コロンは引用符で囲まれていないことに注意してください。次に、変数名自体が引用符で囲まれています。奇妙な構文、私は知っています。これは psql でのみ機能します。(たとえば)PgAdmin-IIIでは機能しません。

この置換は psql での入力処理中に発生するため、 の値を使用してセッションごとに変化すること:'filepath'を期待する関数を (たとえば) 定義することはできません。:'filepath'関数が定義されたときに一度置換され、その後は定数になります。スクリプティングには便利ですが、実行時の使用には役立ちません。

于 2012-11-10T03:12:46.357 に答える
15

FWIW、本当の問題は、 \set コマンドの最後にセミコロンを含めたことです。

\set owner_password 'thepassword';

セミコロンは、変数内の実際の文字として解釈されました。

\echo :owner_password thepassword;

だから私はそれを使用しようとしたとき:

CREATE ROLE myrole LOGIN UNENCRYPTED PASSWORD :owner_password NOINHERIT CREATEDB CREATEROLE VALID UNTIL '無限';

...私はこれを得た:

CREATE ROLE myrole LOGIN UNENCRYPTED PASSWORD thepassword; NOINHERIT CREATEDB CREATEROLE VALID UNTIL '無限';

これは、リテラルを引用符で囲むのに失敗しただけでなく、コマンドを 2 つの部分に分割しました (2 つ目は "NOINHERIT" で始まったため無効でした)。

この話の教訓: PostgreSQL の「変数」は実際にはテキスト展開で使用されるマクロであり、真の値ではありません。便利だと思いますが、最初は難しいです。

于 2008-08-31T17:14:56.817 に答える
11

postgres (バージョン 9.0 以降) は、サポートされているサーバー側スクリプト言語のいずれかで匿名ブロックを許可します

DO '
DECLARE somevariable int = -1;
BEGIN
INSERT INTO foo VALUES ( somevariable );
END
' ;

http://www.postgresql.org/docs/current/static/sql-do.html

すべてが文字列内にあるため、代入される外部文字列変数はエスケープして 2 回引用符で囲む必要があります。代わりにドル クォートを使用しても、SQL インジェクションに対する完全な保護は得られません。

于 2016-05-10T23:02:33.613 に答える
11

SQL proc 言語ではなく、PL/pgSQL などの手続き型言語のいずれかを使用する必要があります。PL/pgSQL では、SQL ステートメントで直接 vars を使用できます。一重引用符の場合は、引用リテラル関数を使用できます。

于 2008-09-22T05:57:25.063 に答える
5

別のアプローチは、PostgreSQL GUC メカニズムを (ab) 使用して変数を作成することです。詳細と例については、この前の回答を参照してください。

で GUC を宣言し、実行時にコマンドpostgresql.confでその値を変更し、 でその値を取得します。SETcurrent_setting(...)

これを一般的に使用することはお勧めしませんが、リンクされた質問で言及されているような狭いケースでは役立つ可能性があります.

于 2012-11-10T03:13:56.573 に答える
5

一時テーブルで解決しました。

CREATE TEMP TABLE temp_session_variables (
    "sessionSalt" TEXT
);
INSERT INTO temp_session_variables ("sessionSalt") VALUES (current_timestamp || RANDOM()::TEXT);

このようにして、セッションに固有の、複数のクエリで使用できる「変数」ができました。同じユーザー名でユーザーをインポートする場合、競合が発生しないようにしながら、一意の「ユーザー名」を生成する必要がありました。

于 2014-10-27T13:07:37.397 に答える
3

この質問と回答は非常に便利ですが、混乱を招くこともあります。引用符で囲まれた変数を機能させるのに多くの問題があったので、これが私がそれを機能させる方法です:

\set deployment_user username    -- username
\set deployment_pass '\'string_password\''
ALTER USER :deployment_user WITH PASSWORD :deployment_pass;

このようにして、1つのステートメントで変数を定義できます。これを使用すると、一重引用符が変数に埋め込まれます。

ノート!引用された変数の後にコメントを入れると、他の回答のいくつかのメソッドを試したときに、変数の一部として吸い込まれました。それは本当にしばらくの間私を台無しにしていました。この方法では、コメントは期待どおりに扱われるように見えます。

于 2012-03-28T15:23:06.417 に答える
2

その機能が本当に恋しいです。同様のことを実現する唯一の方法は、関数を使用することです。

私はそれを2つの方法で使用しました:

  • $_SHARED 変数を使用する perl 関数
  • 変数をテーブルに保存する

Perl バージョン:

   CREATE FUNCTION var(name text, val text) RETURNS void AS $$
        $_SHARED{$_[0]} = $_[1];
   $$ LANGUAGE plperl;
   CREATE FUNCTION var(name text) RETURNS text AS $$
        return $_SHARED{$_[0]};
   $$ LANGUAGE plperl;

テーブルのバージョン:

CREATE TABLE var (
  sess bigint NOT NULL,
  key varchar NOT NULL,
  val varchar,
  CONSTRAINT var_pkey PRIMARY KEY (sess, key)
);
CREATE FUNCTION var(key varchar, val anyelement) RETURNS void AS $$
  DELETE FROM var WHERE sess = pg_backend_pid() AND key = $1;
  INSERT INTO var (sess, key, val) VALUES (sessid(), $1, $2::varchar);
$$ LANGUAGE 'sql';

CREATE FUNCTION var(varname varchar) RETURNS varchar AS $$
  SELECT val FROM var WHERE sess = pg_backend_pid() AND key = $1;
$$ LANGUAGE 'sql';

ノート:

  • plperlu は perl よりも高速です
  • pg_backend_pid は最適なセッション識別ではありません。pid を pg_stat_activity の backend_start と組み合わせて使用​​することを検討してください
  • このテーブルのバージョンも悪いです。これは時々クリアする必要があるためです (現在作業中のセッション変数を削除しないでください)。
于 2012-12-19T21:54:36.637 に答える