PostgreSQL : 명령 줄에서 매개 변수를 전달하는 방법은 무엇입니까?


94

?자리 표시자를 사용하는 스크립트에 다소 자세한 쿼리가 있습니다. 이 동일한 쿼리를 psql 명령 줄 (스크립트 외부)에서 직접 테스트하고 싶었습니다. 들어가서 모든 것을 ?실제 값으로 바꾸는 것을 피하고 대신 쿼리 후에 인수를 전달하고 싶습니다.

예:

SELECT  * 
FROM    foobar
WHERE   foo = ?
   AND  bar = ?
    OR  baz = ?  ;

다음과 같은 것을 찾고 있습니다.

%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };

더 많은 맥락을 부탁드립니다. 이 쿼리가 SQL 파일, Perl / Python / Ruby / <여기에 선호하는 스크립팅 언어 삽입> 스크립트 또는 다른 위치에 있습니까?

@Jack : psql 프롬프트 (명령 줄)에서 직접이 작업을 수행하려고합니다. 스크립트에서 코드를 가져 왔지만 전체 찾기 / 바꾸기 프로세스를 거치고 싶지 않습니다.
vol7ron 2011 년

@ Vol7ron, psql 명령 줄 예제는 아래 내 대답을 참조하십시오.
MAbraham1 2012

1
@ MAbraham1 : 좋습니다. 내 질문에 대한 배경 지식을 좀 더 제공해야했습니다. 열린 텍스트로 SQL이있는 스크립트가 많이 있습니다. 때로는 디버깅을위한 사용자 지정 값을 사용하여 데이터베이스에 직접 적중하는 것이 유용합니다. 추가 파일을 저장할 필요없이 Postgres 내에서 쉽게 수행 할 수있는 방법을 찾고있었습니다.
vol7ron

@ Vol7ron, 감사합니다. 일괄 작업 측면에서 생각했지만 오픈 SQL에서도 토큰을 사용할 수 있어야합니다. 내 대답이 마음에 들면 투표하는 것을 잊지 마십시오.
MAbraham1 2012

답변:


181

-v 구문을 사용할 수 있습니다.

psql -v v1=12  -v v2="'Hello World'" -v v3="'2010-11-12'"

그런 다음 SQL의 변수를 : v1, : v2 등으로 참조하십시오.

select * from table_1 where id = :v1;

두 개의 따옴표를 사용하여 문자열 / 날짜 값을 전달하는 방법에주의하십시오. " '...' "


2
+1 흥미롭고 명명 된 인수 전달. 로그인 한 후이를 수행하는 방법을 알고 있습니까?
vol7ron 2011 년

9
물론 \set v3 'another value'입니다.. SQL 문에서 값을 인용해야하는 경우 다음과 같이 변수 이름 주위에 아포스트로피를 사용하십시오.SELECT * FROM foo WHERE bar = :'v3';
Cromax

2
나는 그들이 그에서 가지고 추측awk
닐 맥기

1
@ 대신 사용할 수 있습니다 : SQLSERVER처럼
Awais 마흐무드에게

5
이 글을 읽으면서 -v로 설정된 변수가 -c로 실행되는 명령에 사용 가능하다는 것을 알고 싶었지만 아쉽게도 그렇지 않습니다. 즉, psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;' 구문 오류가 발생합니다. 그러나 bash가 셸인 경우 다음 psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;' 을 시도해 볼 수 있습니다 .
malcook

31

PostgreSQL에서 찾은 것처럼 스크립팅 언어에서와 마찬가지로 PREPARE명령문 을 작성할 수 있습니다. 불행히도 여전히를 사용할 수 없지만 표기법 ?을 사용할 수 있습니다 $n.

위의 예를 사용하여 :

PREPARE foo(text,text,text) AS
    SELECT  * 
    FROM    foobar
    WHERE   foo = $1
       AND  bar = $2
        OR  baz = $3  ;
EXECUTE foo('foo','bar','baz');
DEALLOCATE foo;

@IvanBlack에 포함시키려는 다른 것이 있었습니까? :) 할당 해제는 세션 종료시 자동으로 수행됩니다
vol7ron

이제는 사용 foo중이며 PREPARE현재 세션이 닫히지 않은 동안 다른 이름은 다른 이름을 가져야합니다. 당신은 노는 경우 PREPAREpsql는 새 이름 때마다를 발명하기 어렵다과 DEALLOCATE) = 그것으로 도움이 될 수 있습니다
이반 블랙

언급 해 주셔서 감사합니다. 한동안 PREPARE를 사용하지 않았지만 유용한 정보입니다
vol7ron

이 솔루션은 IMO가 매우 좋습니다. 유용한 부작용-준비된 문을 여러 번 쉽게 호출 할 수 있습니다.
Yuri

13

psql에는 다음을 통한 메커니즘이 있습니다.

\set name val

명령 -v name=val줄 옵션에 연결되어 있어야합니다 . 인용은 고통 스럽습니다. 대부분의 경우 전체 쿼리 고기를 쉘 here-document 안에 넣는 것이 더 쉽습니다.

편집하다

죄송합니다. (포맷 옵션을위한) -v대신 -P이전 답변이 제대로 되었다고 말 했어야 했습니다.


7

psql 명령 줄 또는 배치 파일에서 매개 변수를 전달할 수도 있습니다. 첫 번째 명령문은 데이터베이스 연결에 필요한 세부 정보를 수집합니다.

마지막 프롬프트는 WHERE 열 IN () 절에서 사용될 제약 조건 값을 요청합니다. 문자열 인 경우 작은 따옴표를 사용하고 쉼표로 구분하십시오.

@echo off
echo "Test for Passing Params to PGSQL"
SET server=localhost
SET /P server="Server [%server%]: "

SET database=amedatamodel
SET /P database="Database [%database%]: "

SET port=5432
SET /P port="Port [%port%]: "

SET username=postgres
SET /P username="Username [%username%]: "

SET /P bunos="Enter multiple constraint values for IN clause [%constraints%]: "
ECHO you typed %constraints%
PAUSE
REM pause
"C:\Program Files\PostgreSQL\9.0\bin\psql.exe" -h %server% -U %username% -d %database% -p %port% -e -v v1=%constraints% -f test.sql

이제 SQL 코드 파일에서 WHERE 절 또는 SQL의 다른 곳에 v1 토큰을 추가합니다. 토큰은 파일뿐만 아니라 열린 SQL 문에서도 사용할 수 있습니다. 이것을 test.sql로 저장하십시오.

SELECT * FROM myTable
WHERE NOT someColumn IN (:v1);

Windows에서는 전체 파일을 DOS BATch 파일 (.bat)로 저장하고 test.sql을 동일한 디렉토리에 저장 한 다음 배치 파일을 실행합니다.

원본 프롬프트 스크립트에 대해 EnterpriseDB의 Dave Page에게 감사드립니다.


Windows 예제의 경우 +1; 대부분의 Pg 데이터베이스가 * nix 변형에 존재하지만
vol7ron

2

당신이 요청한 것은 명령 줄에서 직접 수행 할 수없는 것처럼 보입니다 . plpgsql에서 사용자 정의 함수를 사용하거나 스크립팅 언어에서 쿼리를 호출해야합니다 (후자의 접근 방식을 사용하면 SQL 삽입을 더 쉽게 피할 수 있습니다).


내가 아니 었어-익명으로 남겨진 경우에도 반대표에 일종의 설명 (우리가 질문을 종결하기 위해 투표하는 이유와 유사)이 필요하기를 여러 번 바랍니다.
vol7ron

0

@malcook의 의견 (bash 사용)에서 영감을 얻은 또 다른 답변을 제공하고 싶습니다.

이 옵션은 플래그사용할 때 쿼리 내에서 쉘 변수-c사용해야하는 경우에 적합합니다 . 특히, 이름이 쉘 변수 (사용할 때 직접 전달할 수없는) 인 테이블의 개수를 얻고 싶었습니다.-c .

쉘 변수가 있다고 가정하십시오.

$TABLE_NAME='users'

그런 다음 사용하여 결과를 얻을 수 있습니다.

psql -q -A -t -d databasename -c <<< echo "select count(*) from $TABLE_NAME;"

(그만큼 -q -A -t 추가 서식없이 결과 번호를 인쇄하기위한 것입니다)

나는이 점에 유의한다 echo여기에 문자열합니다 (에서 <<<운영자) 필요하지 않을 수도있다, 내가 원래 그 자체로 따옴표가 어쩌면 누군가가 그 이유를 명확히 할 수 괜찮을 거라 생각 했어요.


0

더 나은 버전의 @ vol7ron 답변을 사용했습니다.

DO $$
BEGIN
    IF NOT EXISTS(SELECT 1 FROM pg_prepared_statements WHERE name = 'foo') THEN
        PREPARE foo(text,text,text) AS
            SELECT  * 
            FROM    foobar
            WHERE   foo = $1
                AND bar = $2
                OR  baz = $3;
    END IF;
END$$;
EXECUTE foo('foo','bar','baz');

이렇게하면 항상이 순서 (아직 준비되지 않은 경우에만 준비된 쿼리)로 실행하고 실행을 반복하고 마지막 쿼리에서 결과를 가져올 수 있습니다.

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