PostgreSQL 쿼리에서 변수를 선언하는 방법


241

PostgreSQL 8.3 쿼리에서 사용할 변수를 어떻게 선언합니까?

MS SQL Server에서 다음을 수행 할 수 있습니다.

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

PostgreSQL에서 동일한 작업을 수행하려면 어떻게합니까? 문서에 따르면 변수는 단순히 "이름 유형;"으로 선언되지만 구문 오류가 발생합니다.

myvar INTEGER;

누군가 나에게 올바른 구문의 예를 줄 수 있습니까?


2
PostgreSQL에서만 가능합니다. 이 관련 질문에 대한 답변을 참조하십시오 : stackoverflow.com/questions/766657/…
Sean the Bean

2
이 관련 답변에 대한 답변이 더 낫습니다. stackoverflow.com/questions/13316773/…
Erwin Brandstetter

답변:


113

PostgreSQL에는 그러한 기능이 없습니다. pl / PgSQL (또는 다른 pl / *)에서만 수행 할 수 있지만 일반 SQL에서는 수행 할 수 없습니다.

예외는 WITH ()변수 또는 변수로 작동 할 수있는 쿼리입니다 tuple. 임시 값 테이블을 리턴 할 수 있습니다.

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) > ...;

이 CTE 방법을 바이러스 백신으로 사용해 보았습니다. 그러나 CTE의 다른 데이터 수정 쿼리가 서로의 영향을 보지 못한다는 문제가 빨리 발생했습니다. 여러 쿼리에서 해당 변수를 사용하려면 여러 CTE를 사용해야했습니다.
Zia Ul Rehman Mughal

228

나는 WITH조항 을 사용하여 동일한 목표를 달성했습니다. 아주 우아하지는 않지만 같은 일을 할 수는 없습니다. 이 예제에서는 정말 과잉입니다. 나는 또한 이것을 추천하지 않습니다.

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

2
이것은 변수를 원하는 대부분의 경우에 효과적입니다. 그러나 LIMIT (변수를 포함 할 수 없음)에 변수를 사용하려면 \setShahriar Aghajani의 답변에서 제안한대로 사용하고 싶습니다 .
cimmanon

1
관계형 데이터를 가져 오려는 마이그레이션 스크립트가있는 경우에 이상적입니다. 분명히 관계형 데이터가 제공되는 시퀀스 ID를 알 수 없습니다.
Relequestual

3
방금이 접근법을 시도하고 더 나은 방법을 찾았습니다. JOIN myconstants ON true그런 다음 하위 선택을 수행 할 필요가 없습니다.
vektor

7
이것은 단일 쿼리 내에서만 작동 WITH하며 트랜잭션의 쿼리간에 CTE를 공유 할 수 없습니다 .
데니스

2
오래된 질문이지만 여기에 변형이 WITH constants AS (SELECT 5 AS var) SELECT * FROM somewhere CROSS JOIN constants WHERE someting=var;있습니다. 단일 행 테이블 표현식이있는 CROSS JOIN은 실제 테이블의 모든 행에 대한 데이터를 사실상 복제하고 표현식을 단순화합니다.
Manngo

83

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 이상이 필요합니다.


1
DO 문은 PostgreSQL 9.0에서 추가되었으며 8.3에서는 작동하지 않습니다.
Johny

14
CREATE TABLE이 아닌 CREATE TEMPORARY TABLE 또는 CREATE TEMP TABLE을 사용하십시오. 그러나 그렇지 않으면 괜찮습니다.
Stefan Steiger

60

동적 구성 설정

이를 위해 동적 구성 설정을 "남용"할 수 있습니다.

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

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

구성 설정은 항상 varchar 값이므로 사용할 때 올바른 데이터 유형으로 캐스트해야합니다. 이것은 모든 SQL 클라이언트 \set에서 작동 하지만psql

위의 Postgres 9.2 이상이 필요합니다.

이전 버전에서는 변수 postgresql.conf를 사용하기 전에 선언 해야했기 때문에 사용 편의성이 다소 제한되었습니다. 실제로 변수는 완전하지 않지만 기본적으로 접두사 인 구성 "클래스"입니다. 그러나 접두사가 정의되면 모든 변수를 변경하지 않고 사용할 수 있습니다.postgresql.conf


3
@BrijanElwadhi : 그렇습니다.
a_horse_with_no_name

2
참고로 : 일부 단어는 예약과 같이 예약되어 있습니다. set session my.vars.id = '1';set session my.user.id = '1';얻을 것입니다ERROR: syntax error at or near "user"
도미니크

2
@BrijanElwadhi : 변수 트랜잭션을 특정하게하려면 다음을 사용해야합니다 SET LOCAL ..... 연결하는 한 session변수가 적용됩니다. 는 local트랜잭션 범위가.
유겐 콘 코프

당신은 따옴표와 함께 그 한계를 주위를 얻을 수 있습니다 예를 들어. @dominik, 예상대로 호출이 작동합니다.set session "my.user.id" = '1';current_setting('my.user.id')
Miles Elam

58

클라이언트에 따라 다릅니다.

그러나 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';

1
\set소문자 여야 함
deluan

db = # \ set profile_id 102 db = # : profile_id; 오류 : "102"또는 그 근처에 구문 오류 LINE 1 : 102; ^
AlxVallejo

1
@AlxVallejo 문장과 psql 콘솔 에서 사용해야합니다 . db=> \set someid 8292 db=> SELECT * FROM sometable WHERE id = :someid;
everis

21

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;

13

@DarioBarrionuevo의 답변을 개선 하여 임시 테이블을보다 간단하게 활용할 수 있도록 제안하고 싶습니다 .

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;

DO 블록을 해결하기위한 훌륭한 솔루션은 데이터 세트를 반환 할 수 없습니다!
CodeFarmer

PostgreSQL 11.0에서 이러한 쿼리는 1의 내용이 아닌 (아마도 행 수)를 반환합니다 tmp_table.
Ed Noepel

9

이 솔루션은 fei0x에서 제안한 솔루션을 기반으로 하지만 쿼리에서 상수 값 목록에 참여할 필요가 없으며 쿼리 시작시 상수를 쉽게 나열 할 수 있다는 장점이 있습니다. 재귀 쿼리에서도 작동합니다.

기본적으로 모든 상수는 WITH 절에 선언 된 단일 값 테이블 이며 나머지 쿼리 부분에서 호출 할 수 있습니다.

  • 두 개의 상수가있는 기본 예 :
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)

또는 postgresql과 다른 다른 쿼리 언어에는 유효하지 않은 SELECT * FROM constant_name대신 사용할 수 있습니다 TABLE constant_name.


6

다음은 PREPARE 문을 사용하는 예 입니다. 여전히을 사용할 수는 없지만 표기법 ?을 사용할 수 있습니다 $n.

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

잘 작동합니다! 감사.
Rui Carvalho

4

사실, 단일 값 변수를 선언하는 생생하고 명확한 방법은 없습니다.

with myVar as (select "any value really")

그런 다음이 구성에 저장된 값에 액세스하려면

(select * from myVar)

예를 들어

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

3

공구 특수 기능에 의지 할 수 있습니다. DBeaver 고유의 독점 구문과 유사합니다.

@set name = 'me'
SELECT :name;
SELECT ${name};

DELETE FROM book b
WHERE b.author_id IN (SELECT a.id FROM author AS a WHERE a.name = :name);

이것은 사용하기에 더 가깝습니다 : DBeaver가 목록과 반복을 지원하는지 여부를 살펴볼 것입니다. 동일한 스키마를 여러 스키마에 적용해야하며 목록은 스키마에 적용됩니다.
javadba

1

DBeaver에서는 코드에서와 마찬가지로 쿼리에서 매개 변수를 사용할 수 있으므로 다음과 같이 작동합니다.

SELECT *
FROM somewhere
WHERE something = :myvar

쿼리를 실행할 때 DBeaver는 : myvar에 대한 값을 묻고 쿼리를 실행합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.