[sql] psql에서 스크립트 변수를 어떻게 사용합니까?

MS SQL Server에서 사용자 정의 변수를 사용하는 스크립트를 작성합니다.

DECLARE @somevariable int
SELECT @somevariable = -1

INSERT INTO foo VALUES ( @somevariable )

그런 다음 @somevariable특정 상황에서 원하는 값에 따라 런타임시 값을 변경합니다 . 스크립트 상단에 있기 때문에보고 기억하기 쉽습니다.

PostgreSQL 클라이언트와 동일한 작업을 수행하려면 어떻게합니까 psql?



답변

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;


답변

PSQL 변수에 대한 마지막 단어 :

  1. SQL 문에서 작은 따옴표로 묶으면 확장되지 않습니다. 따라서 이것은 작동하지 않습니다.

    SELECT * FROM foo WHERE bar = ':myvariable'
  2. SQL 문에서 문자열 리터럴로 확장하려면 변수 세트에 따옴표를 포함시켜야합니다. 그러나 변수 값은 이미 따옴표로 묶어야합니다. 즉, 두 번째 따옴표 세트가 필요 하고 내부 세트를 이스케이프해야합니다. 따라서 다음이 필요합니다.

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

    편집 : PostgreSQL 9.1부터 다음과 같이 작성할 수 있습니다.

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

답변

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;


답변

특히 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'을 변경 하고 사용 하는 값 을 사용 하고 기대 하는 함수를 정의 할 수 없습니다 . 함수가 정의되면 한 번 대체되고 그 후에 상수가됩니다. 스크립팅에는 유용하지만 런타임에는 사용하지 않습니다.


답변

FWIW, 진짜 문제는 \ set 명령 끝에 세미콜론을 포함 시켰다는 것입니다.

\ set owner_password ‘thepassword’;

세미콜론은 변수에서 실제 문자로 해석되었습니다.

\ echo : owner_password thepassword;

그래서 그것을 사용하려고했을 때 :

역할 미롤 생성 로그인 암호 : owner_password 아니요 CREATEDB CREATEROLE이 유효 할 때까지 ‘무한대’;

…알 겠어:

역할 myrole 작성 암호화되지 않은 비밀번호 thepassword; ‘무한대’가 될 때까지 CREATEDB CREATEROLE이 유효하지 않습니다.

이것은 리터럴 주위에 따옴표를 설정하는 데 실패했을뿐만 아니라 명령을 2 부분으로 나누었습니다 (두 번째 부분은 “NOINHERIT”로 시작하여 유효하지 않습니다).

이 이야기의 교훈 : PostgreSQL “변수”는 실제 값이 아니라 텍스트 확장에 사용되는 매크로입니다. 나는 그것이 유용하다고 확신하지만 처음에는 까다 롭습니다.


답변

SQL proc 언어가 아닌 PL / pgSQL과 같은 절차 적 언어 중 하나를 사용해야합니다. PL / pgSQL에서는 SQL 문에서 바로 vars를 사용할 수 있습니다. 작은 따옴표의 경우 따옴표 리터럴 함수를 사용할 수 있습니다.


답변

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

모든 것이 문자열 안에 있기 때문에 대체되는 외부 문자열 변수는 이스케이프되고 두 번 인용되어야합니다. 달러 따옴표를 대신 사용하면 SQL 삽입을 완벽하게 보호 할 수 없습니다.