web-dev-qa-db-ja.com

PostgreSQLクエリで変数を宣言する方法

PostgreSQL 8.3クエリで使用する変数をどのように宣言しますか?

MS SQL Serverではこれが可能です。

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

PostgreSQLで同じことをするにはどうすればいいですか?ドキュメントによれば、変数は単に "name type;"として宣言されていますが、これは私に構文エラーを与えます。

myvar INTEGER;

誰かが私に正しい構文の例を教えてもらえますか?

180
EMP

PostgreSQLにはそのような機能はありません。それはpl/PgSQL(または他のpl/*)でのみ可能ですが、プレーンSQLではできません。

例外は、変数として、または変数のTupleとしても機能することができるWITH ()クエリです。それはあなたが一時的な値のテーブルを返すことを可能にします。

WITH master_user AS (
    SELECT
      login,
      registration_date
    FROM users
    WHERE ...
)

SELECT *
FROM users
WHERE master_login = (SELECT login
                      FROM master_user)
      AND (SELECT registration_date
           FROM master_user) > ...;
83
user80168

私は WITH を使って同じ目標を達成しました。それほど洗練されたものではありませんが、同じことができます。この例では、本当にやり過ぎです。私は特にこれをお勧めしません。

WITH myconstants (var1, var2) as (
   values (5, 'foo')
)
SELECT *
FROM somewhere, myconstants
WHERE something = var1
   OR something_else = var2;
174
fei0x

PLPGSQLでもこれを試すことができます。

DO $$
DECLARE myvar integer;
BEGIN
    SELECT 5 INTO myvar;

    DROP TABLE IF EXISTS tmp_table;
    CREATE TABLE tmp_table AS
    SELECT * FROM yourtable WHERE   id = myvar;
END $$;

SELECT * FROM tmp_table;

上記はPostgres 9.0以降が必要です。

65

それはあなたのクライアント次第です。

ただし、psqlクライアントを使用している場合は、次のものを使用できます。

my_db=> \set myvar 5
my_db=> SELECT :myvar  + 1 AS my_var_plus_1;
 my_var_plus_1 
---------------
             6

あなたがテキスト変数を使っているならば、あなたは引用する必要があります。

\set myvar 'sometextvalue'
select * from sometable where name = :'myvar';
43

動的構成設定

あなたはこれのために動的設定を "悪用"することができます。

-- choose some prefix that is unlikey to be used by postgres
set session my.vars.id = '1';

select *
from person 
where id = current_setting('my.vars.id')::int;

構成設定は常にvarchar値であるため、それらを使用するときは正しいデータ型にキャストする必要があります。 \setpsqlでのみ機能しますが、これはどのSQLクライアントでも機能します。

上記にはPostgres 9.2以降が必要です。

以前のバージョンでは、変数は使用される前にpostgresql.confで宣言されなければなりませんでした、それでそれはその有用性を幾分制限しました。実際には完全に変数ではなく、基本的に接頭辞であるconfig "class"です。しかし、一度接頭辞が定義されると、postgresql.confを変更せずに任意の変数を使用できます。

39

Pl/PgSQLの外部で一時テーブルを使用する

提案されているようにpl/pgsqlまたは他のpl/*言語を使用する以外に、これが私が考えることができる唯一の他の可能性です。

begin;
select 5::int as var into temp table myvar;
select *
  from somewhere s, myvar v
 where s.something = v.var;
commit;
19
joatmon

一時テーブルをより簡単に活用するために、 @ DarioBarrionuevo's answer に改善を提案したいと思います。

DO $$
    DECLARE myvar integer = 5;
BEGIN
    CREATE TEMP TABLE tmp_table ON COMMIT DROP AS
        -- put here your query with variables:
        SELECT * 
        FROM yourtable
        WHERE id = myvar;
END $$;

SELECT * FROM tmp_table;
9
bluish

これは PREPARE文 を使った例です。まだ?を使用することはできませんが、$n表記を使用することはできます。

PREPARE foo(integer) AS
    SELECT  *
    FROM    somewhere
    WHERE   something = $1;
EXECUTE foo(5);
DEALLOCATE foo;
5
Martin Zinovsky

この解決策は、 fei0x によって提案されたものに基づいていますが、クエリ内の定数の値リストを結合する必要がなく、クエリの開始時に定数を簡単にリストできるという利点があります。再帰的なクエリでも機能します。

基本的に、すべての定数はWITH値の中の単一値のテーブルdeclaratedであり、クエリの残りの部分のどこでも呼び出すことができます。

  • 2つの定数を使った基本的な例
WITH
    constant_1_str AS (VALUES ('Hello World')),
    constant_2_int AS (VALUES (100))
SELECT *
FROM some_table
WHERE table_column = (table constant_1_str)
LIMIT (table constant_2_int)

あるいは、SELECT * FROM constant_nameの代わりにTABLE constant_nameを使用することもできます。これは、postgresqlとは異なる他のクエリ言語には無効な場合があります。

4
Jorge Luis

確かに、単一値の変数を宣言するための鮮明で明確な方法はありません。できることは

with myVar as (select "any value really")

次に、この構造に格納されている値にアクセスするには、

(select * from myVar)

例えば

with var as (select 123)    
... where id = (select * from var)
1