source

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

manysource 2023. 6. 4. 10:37

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

MS SQL Server에서 사용자 지정 가능한 변수를 사용하기 위해 스크립트를 만듭니다.

DECLARE @somevariable int  
SELECT @somevariable = -1

INSERT INTO foo VALUES ( @somevariable )

▁value▁the다니합변▁i경▁change'▁then의 값을 변경하겠습니다.@somevariable특정 상황에서 내가 원하는 값에 따라 런타임에.대본의 맨 위에 있기 때문에 쉽게 보고 기억할 수 있습니다.

PostgrePostgre에서 하려면 어떻게 해야 ?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
    

    편집: Postgre로 시작SQL 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를 사용할 수 . 를 전달할 때는 " 행의변사수있다습니할용명수도령다▁variables▁from니▁them있▁pass"를 할 수 있습니다.-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에서 입력 ▁this▁a▁usessay▁can다▁process를 사용하는 함수를 정의 수 없습니다.:'filepath'은 그고그가기대니다합를치리▁of▁the▁value▁and▁expect다니기대.:'filepath'세션 간에 변경할 수 있습니다.함수가 정의될 때 한 번 대체되고 그 이후에는 상수가 됩니다.스크립팅에는 유용하지만 런타임에는 사용할 수 없습니다.

FWIW, 실제 문제는 \set 명령어 끝에 세미콜론을 포함했다는 것입니다.

\set owner_password '비밀번호';

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

\filename:owner_password 비밀번호;

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

CREATE ROLE myrole 로그인 암호화되지 않은 비밀번호 :owner_password 'infinity'까지 유효한 상속 작성자 역할이 없습니다.

...알겠습니다.

CREATE ROLE myrole 암호화되지 않은 로그인 비밀번호, 'infinity'까지 유효한 상속 CREATE B CREATEROLE이 없습니다.

이는 리터럴 주위에 따옴표를 설정하는 데 실패했을 뿐만 아니라 명령을 두 부분으로 나눕니다(두 번째 부분은 "NO INHERIT"로 시작했기 때문에 유효하지 않습니다.

이 이야기의 교훈: PostgreSQL "변수"는 실제 텍스트 확장에 사용되는 매크로이지 실제 값이 아닙니다.그게 도움이 될 거라고 확신하지만, 처음에는 까다롭습니다.

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 주입을 완벽하게 방지할 수 없습니다.

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

저는 그것을 임시 테이블로 해결했습니다.

CREATE TEMP TABLE temp_session_variables (
    "sessionSalt" TEXT
);
INSERT INTO temp_session_variables ("sessionSalt") VALUES (current_timestamp || RANDOM()::TEXT);

이렇게 하면 세션에 고유한 여러 쿼리에 사용할 수 있는 "변수"가 있습니다.동일한 사용자 이름을 가진 사용자를 가져올 경우 충돌이 발생하지 않으면서 고유한 "사용자 이름"을 생성하기 위해 필요했습니다.

또 다른 접근 방식은 Postgre를 사용하는 것입니다.변수를 생성하는 SQL GUC 메커니즘입니다.자세한 내용과 예제는 이 이전 답변을 참조하십시오.

를 "GUC"로 합니다.postgresql.conf 시 할 때 다런변값다니경합을에타임음▁its▁at▁then다▁changeSET를 사용하여 .current_setting(...).

일반적인 용도로는 권장하지 않지만, 포스터가 트리거 및 기능에 응용 프로그램 수준의 사용자 이름을 제공하는 방법을 원했던 링크된 질문에 언급된 경우와 같은 좁은 경우에 유용할 수 있습니다.

저는 이 질문과 대답이 매우 유용하면서도 혼란스럽다는 것을 알게 되었습니다.인용된 변수를 작동시키는 데 많은 어려움을 겪었기 때문에 다음과 같이 작동했습니다.

\set deployment_user username    -- username
\set deployment_pass '\'string_password\''
ALTER USER :deployment_user WITH PASSWORD :deployment_pass;

이렇게 하면 변수를 하나의 문에 정의할 수 있습니다.사용 시 변수에 작은 따옴표가 포함됩니다.

참고! 인용된 변수 뒤에 주석을 달았을 때 다른 답변에서 몇 가지 방법을 시도했을 때 변수의 일부로 빨려 들어갔습니다.그것은 한동안 저를 정말로 망치게 했습니다.이 방법을 사용하면 설명이 예상대로 처리되는 것 같습니다.

저는 그 기능이 정말 그립습니다.비슷한 것을 달성하는 유일한 방법은 기능을 사용하는 것입니다.

두 가지 방법으로 사용해 왔습니다.

  • $_SHARED 변수를 사용하는 perl 함수
  • 변수를 표에 저장

Perl 버전:

   CREATE FUNCTION var(name text, val text) RETURNS void AS $$
        $_SHARED{$_[0]} = $_[1];
   $$ LANGUAGE plperl;
   CREATE FUNCTION var(name text) RETURNS text AS $$
        return $_SHARED{$_[0]};
   $$ LANGUAGE plperl;

테이블 버전:

CREATE TABLE var (
  sess bigint NOT NULL,
  key varchar NOT NULL,
  val varchar,
  CONSTRAINT var_pkey PRIMARY KEY (sess, key)
);
CREATE FUNCTION var(key varchar, val anyelement) RETURNS void AS $$
  DELETE FROM var WHERE sess = pg_backend_pid() AND key = $1;
  INSERT INTO var (sess, key, val) VALUES (sessid(), $1, $2::varchar);
$$ LANGUAGE 'sql';

CREATE FUNCTION var(varname varchar) RETURNS varchar AS $$
  SELECT val FROM var WHERE sess = pg_backend_pid() AND key = $1;
$$ LANGUAGE 'sql';

주의:

  • plperlu는 perl보다 빠릅니다.
  • pg_start_pid는 최상의 세션 식별이 아닙니다. pg_stat_activity에서 backend_start와 결합된 pid를 사용하는 것을 고려해 보십시오.
  • 이 테이블 버전은 또한 좋지 않습니다. 이 테이블 버전은 가끔 위의 항목을 지워야 하기 때문입니다(현재 작업 중인 세션 변수는 삭제하지 마십시오).

변수:psql정수를 선언하려면 정수를 입력한 다음 캐리지 리턴을 수행한 다음 세미콜론으로 문을 종료해야 합니다.관찰:

정수 변수를 선언한다고 가정합니다.my_var표에 삽입합니다.test:

예제 표test:

thedatabase=# \d test;
                         Table "public.test"
 Column |  Type   |                     Modifiers                     
--------+---------+---------------------------------------------------
 id     | integer | not null default nextval('test_id_seq'::regclass)
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)

분명히, 이 표에는 아직 아무것도 없습니다.

thedatabase=# select * from test;
 id 
----
(0 rows)

변수를 선언합니다.세미콜론이 다음 줄에 어떻게 있는지 주목하세요!

thedatabase=# \set my_var 999
thedatabase=# ;

이제 삽입할 수 있습니다.우리는 이 이상한 것을 사용해야 합니다.":''구문 보기:

thedatabase=# insert into test(id) values (:'my_var');
INSERT 0 1

효과가 있었어요!

thedatabase=# select * from test;
 id  
-----
 999
(1 row)

설명:

그럼... 다음 줄에 세미콜론이 없으면 어떻게 될까요?변수?확인:

선언합니다my_var새 노선 없이

thedatabase=# \set my_var 999;

선택합니다.my_var.

thedatabase=# select :'my_var';
 ?column? 
----------
 999;
(1 row)

그게 WTF야?정수가 아니라 문자열입니다. 999;!

thedatabase=# select 999;
 ?column? 
----------
      999
(1 row)

에 대한 새로운 해결책을 다른 스레드에 게시했습니다.

테이블을 사용하여 변수를 저장하며 언제든지 업데이트할 수 있습니다.정적 불변 게터 함수는 테이블 업데이트에 의해 트리거되어 동적으로 생성됩니다(다른 함수에 의해).훌륭한 테이블 스토리지와 더불어 불변의 게터의 엄청나게 빠른 속도를 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/36959/how-do-you-use-script-variables-in-psql