60

PostgreSQLクエリで名前付き定数を定義する方法はありますか?例えば:

MY_ID = 5;
SELECT * FROM users WHERE id = MY_ID;
4

5 に答える 5

53

この質問は以前にもありました ( How do you use script variables in PostgreSQL? )。ただし、クエリに時々使用するトリックがあります。

with const as (
    select 1 as val
)
select . . .
from const cross join
     <more tables>

つまり、定数が定義されている const という CTE を定義します。次に、これを任意のレベルで何度でもクエリにクロス結合できます。これは、日付を扱っていて、多くのサブクエリで日付定数を処理する必要がある場合に特に便利です。

于 2012-11-09T22:58:43.310 に答える
46

PostgreSQL には、MySQL や Oracle のような (グローバル) 変数を定義する方法が組み込まれていません。( 「カスタマイズされたオプション」を使用した限定的な回避策があります)。あなたが正確に望むものに応じて、他の方法があります:

1 つのクエリに対して

@Gordon already providedのように、 CTEのクエリの先頭に値を指定できます。

グローバルな永続定数:

そのための簡単なIMMUTABLE関数を作成できます。

CREATE FUNCTION public.f_myid()
  RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT 5';

(並列安全設定は、Postgres 9.6 以降にのみ適用されます。)

現在のユーザーに表示されるスキーマに存在する必要があります。つまり、それぞれのsearch_path. publicデフォルトでは schema と同様です。セキュリティが問題になる場合は、それが の最初のスキーマであることを確認するかsearch_path、呼び出しでスキーマ修飾します。

SELECT public.f_myid();

データベース内のすべてのユーザー ( schema へのアクセスが許可されているpublic) に表示されます。

現在のセッションの複数の値:

CREATE TEMP TABLE val (val_id int PRIMARY KEY, val text);
INSERT INTO val(val_id, val) VALUES
  (  1, 'foo')
, (  2, 'bar')
, (317, 'baz');

CREATE FUNCTION f_val(_id int)
  RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
'SELECT val FROM val WHERE val_id = $1';

SELECT f_val(2);  -- returns 'baz'

plpgsql は作成時にテーブルの存在をチェックするため、関数を作成する前に (一時) テーブルを作成する必要がありますval。関数が存続している間に一時テーブルがセッションの最後に削除された場合でもです。呼び出し時に基になるテーブルが見つからない場合、関数は例外を発生させます。

search_path一時オブジェクトの現在のスキーマは、明示的に指示されていない限り、デフォルトで残りのスキーマよりも優先されます。から一時スキーマを除外することはできませんsearch_pathが、他のスキーマを最初に置くことはできます。
夜の邪悪な生き物 (必要な特権を持つ) は、 をいじくり回してsearch_path、同じ名前の別のオブジェクトを前に置く可能性があります。

CREATE TABLE myschema.val (val_id int PRIMARY KEY, val text);
INSERT INTO val(val_id, val) VALUES (2, 'wrong');

SET search_path = myschema, pg_temp;

SELECT f_val(2);  -- returns 'wrong'

特権ユーザーのみがグローバル設定を変更できるため、それほど脅威ではありません。他のユーザーは、自分のセッションに対してのみ実行できます。を使用した関数の作成SECURITY DEFINERに関するマニュアルの関連する章を検討してください。

ハードワイヤード スキーマは通常、よりシンプルで高速です。

CREATE FUNCTION f_val(_id int)
  RETURNS text LANGUAGE sql STABLE PARALLEL RESTRICTED AS
'SELECT val FROM pg_temp.val WHERE val_id = $1';

より多くのオプションを含む関連する回答:

于 2012-11-09T23:40:48.960 に答える
10

Gordon と Erwin が既に述べた適切なオプション (一時テーブル、定数を返す関数、CTE など) に加えて、PostgreSQL の GUC メカニズムを (ab) 使用して、グローバル、セッション、およびトランザクション レベルの変数を作成することもできます。

アプローチの詳細を示すこの以前の投稿を参照してください。

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

于 2012-11-10T03:07:33.650 に答える