이 문서는 지원되지 않는 버전의 PostgreSQL을위한 것입니다.
당신은에 대해 같은 페이지를 볼 수 있습니다토토 커뮤니티 PostgreSQL : 문서 : 17 : 41.5. 토토 캔 진술버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

40.5. 토토 캔 진술

이 섹션과 다음 섹션에서는 모든 것을 설명합니다. 명시 적으로 이해되는 진술 유형pl/pgsql. 하나로 인식되지 않은 것 이 진술 유형은 SQL 명령으로 추정되며 전송됩니다. 에 설명 된대로 실행할 기본 데이터베이스 엔진에섹션 40.5.2and섹션 40.5.3.

40.5.1. 과제

값의 할당pl/pgsql변수는 다음과 같이 작성되었습니다.

가변: =표현;

앞에서 설명한 바와 같이, 그러한 진술의 표현은 다음과 같습니다. SQL을 통해 평가select기본 데이터베이스 엔진으로 전송 된 명령. 표현은 생성해야합니다 단일 값 (변수가 행 인 경우 행 값일 수 있습니다. 레코드 변수). 대상 변수는 단순한 변수 일 수 있습니다 (선택적으로 블록 이름으로 자격이 있음), 행 필드 또는 레코드 변수 또는 간단한 배열 요소 변수 또는 필드.

표현식의 결과 데이터 유형이 일치하지 않는 경우 변수의 데이터 유형 또는 변수의 특정 크기/정밀도가 있습니다. (좋다char (20)), 결과 값이 될 것입니다 암시 적으로 변환pl/pgsql결과 유형을 사용한 통역사 출력 기능 및 변수 유형의 입력 기능. 주목하십시오 이로 인해 잠재적으로 런타임 오류가 발생할 수 있습니다. 입력 함수, 결과 값의 문자열 양식이 그렇지 않은 경우 입력 함수에 허용됩니다.

예 :

세금 : = 하위 토탈 * 0.06;
my_record.user_id : = 20;

40.5.2. 토토 캔을 실행합니다 결과 없음

예를 들어 행을 반환하지 않는 SQL 명령의 경우삽입a반환절, 내에서 토토 캔을 실행할 수 있습니다 에이pl/pgsql토토 캔 작성.

anypl/pgsql변수 이름 명령 텍스트에 나타나는 것은 매개 변수로 취급됩니다. 변수의 현재 값은 매개 변수로 제공됩니다. 실행 시간에 가치. 이것은 설명 된 처리와 똑같습니다 표현의 경우 더 일찍; 자세한 내용은 참조섹션 40.10.1.

이러한 방식으로 SQL 명령을 실행할 때PL/PGSQL실행을 캐시하고 재사용 할 수 있습니다 토토 캔 계획,섹션 40.10.2.

때로는 표현식 또는를 평가하는 것이 유용합니다.select쿼리 그러나 결과를 폐기하십시오 부작용이 있지만 유용한 결과가없는 함수를 호출 할 때 값.pl/pgsql, 사용 그만큼공연진술 :

공연쿼리;

이것은 실행쿼리그리고 폐기합니다 결과. 쓰기쿼리SQL을 작성하는 것과 마찬가지로select토토 캔이지만 초기 키워드를 대체selectwith공연. 을 위한with쿼리, 사용공연그런 다음 쿼리를 괄호 안에 놓습니다. (안에 이 경우 쿼리는 한 행만 반환 할 수 있습니다.)pl/pgsql변수가 대체됩니다 결과를 반환하지 않는 명령과 같은 쿼리 및 계획 같은 방식으로 캐시됩니다. 또한 특수 변수발견쿼리가 적어도 생성 된 경우 true로 설정됩니다. 행을 생성하지 않은 경우 하나 또는 거짓 (참조섹션 40.5.5).

참고 :그 글쓰기를 기대할 수 있습니다select직접이 결과를 달성하지만 at 그것을 할 수있는 유일한 방법을 제시하는 것입니다공연. 와 같은 행을 반환 할 수있는 SQL 명령select는 오류로 거부됩니다 가 없다면in논의 된 조항 다음 섹션에서.

예 :

create_mv 수행 ( 'CS_SESSICE_PAGE_REQUESTS_MV', MY_QUERY);

40.5.3. a로 쿼리 실행 단일 줄 결과

단일 행을 산출하는 SQL 명령의 결과 (아마도 다중 열)은 레코드 변수, 행 유형에 할당 할 수 있습니다. 변수 또는 스칼라 변수 목록. 이것은 작성하여 수행됩니다 기본 SQL 명령 및 추가in절. 예를 들어,

selectselect_expressions[에엄격한]대상에서 ...;
삽입 ... 반환표현[에엄격한]대상;
업데이트 ... 반환표현[에엄격한]대상;
삭제 ... 반환표현[에엄격한]대상;

여기서대상레코드가 될 수 있습니다 변수, 행 변수 또는 쉼표로 구분 된 간단한 목록 변수 및 레코드/행 필드.pl/pgsql변수가 대체됩니다 쿼리의 나머지 부분과 계획은 설명 된대로 캐시됩니다. 위의 행을 반환하지 않는 명령의 경우. 이것은 |select, 삽입/업데이트/삭제with반환및 행 세트 결과를 반환하는 유틸리티 명령 (예 :설명). 을 제외하고into절, SQL 명령은 동일합니다. 외부에 쓰기pl/pgsql.

팁 :이 해석에 주목하십시오.selectwithinto와 다릅니다postgresql's 정기적인선택명령, 여기서in대상은 새로 생성 된 테이블입니다. 만약에 당신은 a에서 테이블을 만들고 싶습니다.select내부의 결과pl/pgsql함수, 구문 사용테이블 생성 ... AS 선택하다.

행 또는 가변 목록이 대상으로 사용되는 경우 쿼리 결과 열은 대상의 구조와 정확히 일치해야합니다. 숫자 및 데이터 유형 또는 그렇지 않으면 런타임 오류가 발생합니다. 언제 a 레코드 변수는 대상이며 자동으로 자체를 구성합니다 쿼리 결과 열의 행 유형에.

theinto조항이 거의 나타날 수 있습니다 SQL 명령의 어느 곳에서나. 관습 적으로 그것은 단지 작성되었습니다 전 또는 직후select_expressionsinselect토토 캔 또는 토토 캔의 끝에 다른 토토 캔 유형. 당신이 이것을 따르는 것이 좋습니다 대회의 경우pl/pgsqlParser는 향후 버전에서 더 엄격 해집니다.

if엄격한에 지정되어 있지 않습니다.into조항,대상첫 번째 행으로 설정됩니다 쿼리에 의해 또는 쿼리가 행이 반환되지 않은 경우 Nulls에 의해. ("첫 번째 줄"는 잘 정의되어 있지 않습니다 당신이 사용하지 않는 한주문 by.) 모든 결과 첫 번째 행 후 행은 폐기됩니다. 스페셜을 확인할 수 있습니다발견변수 (참조섹션 40.5.5) 행이 반환되었는지 여부를 결정하려면 :

empname = myName에서 EMP에서 MyRec에 * 선택 *;
찾을 수없는 경우
    예외 '직원 % 찾을 수 없음', MyName;
끝 If;

엄격한옵션이 지정되어 있습니다 쿼리는 정확히 하나의 행을 반환해야합니다. 그렇지 않으면 런 타임 오류가 보고 된no_data_found(줄 없음) 또는TOO_MANY_ROWS(하나 이상). 너 오류를 잡으려면 예외 블록을 사용할 수 있습니다. 예:

시작
    Empname = myName에서 Emp에서 Strict Myrec으로 * 선택하십시오.
    예외
        그렇다면 no_data_found 일 때
            예외 '직원 % 찾을 수 없음', MyName;
        언제 너무 _many_rows
            예외를 제기하는 '직원 % 고유하지 않음', MyName;
끝;

토토 캔의 성공적인 실행엄격한항상 설정발견TO 진실.

for삽입/업데이트/삭제with반환, pl/pgsql둘 이상의 오류를보고합니다 반품 행,엄격한그렇지 않습니다 지정되었습니다. 와 같은 옵션이 없기 때문입니다.주문영향을받는 행을 결정하기 위해 반품해야합니다.

참고 :the엄격한옵션 일치 Oracle PL/SQL의 동작선택 안으로및 관련 진술.

여러 결과 행을 처리 해야하는 케이스를 처리하려면 SQL 쿼리에서 참조섹션 40.6.4.

40.5.4. 동적 실행 토토 캔

종종 내부에서 동적 토토 캔을 생성하고 싶을 것입니다 당신의pl/pgsql함수, 즉 다른 테이블 또는 다른 데이터 유형과 관련된 토토 캔 그들이 처형 될 때마다.pl/pgsql의 정상적인 계획을 캐시하려는 시도 토토 캔 (논의 된대로섹션 40.10.2)는 그러한 시나리오에서 작동하지 않습니다. 이런 종류를 처리합니다 문제의execute성명서입니다 제공 :

executeCommand-string[[에엄격한]대상 ] [사용표현[, ... ]];

여기서Command-stringis 문자열을 산출하는 표현 (유형텍스트) 실행되는 명령을 포함합니다. 선택 사항대상레코드 변수, 행 변수입니다. 또는 간단한 변수 및 레코드/행의 쉼표로 구분 된 목록 명령의 결과가 저장되는 필드. 그만큼 선택 과목사용표현식 공급 값 명령에 삽입하려면.

대체 없음pl/pgsql변수는 계산 된 명령 문자열에서 수행됩니다. 필요한 모든 변수 값은 명령 문자열에 삽입해야합니다. 건설; 또는 아래에 설명 된대로 매개 변수를 사용할 수 있습니다.

또한,execute. 대신, 토토 캔은 항상입니다 명세서가 실행될 때마다 계획됩니다. 따라서 토토 캔 문자열은 할 수 있습니다 작업을 수행하기 위해 기능 내에서 동적으로 생성됩니다. 다른 테이블과 열.

thein조항은 위치를 지정합니다 SQL 명령의 결과를 반환하는 행의 결과를 할당해야합니다. 경우 a 행 또는 가변 목록이 제공되며 정확히 일치해야합니다. 쿼리 결과 구조 (레코드 변수가 사용될 때 결과 구조와 일치하도록 구성됩니다 자동으로). 여러 행이 반환되면 첫 번째 의지 만 있습니다 에 할당됩니다.in변수. 아니오 줄이 반환되고 Null은에 할당됩니다.in변수. 그렇지 않은 경우in조항이 지정되어 있으며 쿼리 결과가 있습니다 폐기.

엄격한옵션이 제공됩니다 쿼리가 정확히 하나의 행을 생성하지 않는 한보고됩니다.

명령 문자열은 매개 변수 값을 사용할 수 있습니다 명령에서에 참조$ 1, $ 2등.이 기호는 값을 나타냅니다 에 제공됨사용절. 이 방법 종종 명령에 데이터 값을 삽입하는 것이 바람직합니다. 문자열 텍스트 : 변환의 런 타임 오버 헤드를 피합니다. 텍스트와 뒤로 값, SQL-injection이 훨씬 덜 발생합니다. 인용하거나 탈출 할 필요가 없기 때문에 공격. 예 이다:

실행 'inserted_by = $ 1이고 삽입 된 mytable에서 count (*)를 선택하십시오. <= $ 2'
   c
   Checked_user 사용, Checked_date;

매개 변수 기호는 데이터 값에만 사용할 수 있습니다. 동적으로 결정된 테이블 또는 열 이름을 사용하려면 명령 문자열에 텍스트로 삽입해야합니다. 을 위한 예를 들어, 앞의 쿼리가 동적으로 선택된 테이블, 당신은 이것을 할 수 있습니다 :

execute 'count (*)에서'
    || tabname :: regclass
    || 'inserted_by = $ 1이고 삽입 된 <= $ 2'
   c
   Checked_user 사용, Checked_date;

매개 변수 기호의 또 다른 제한은 그들이 작동한다는 것입니다. 안에select, 삽입, 업데이트삭제명령. 다른 진술 유형에서 (일반적으로 유틸리티 명령문이라고 함) 값을 삽입해야합니다 데이터 값에 불과하더라도 문자로.

anexecute단순한 상수 토토 캔 문자열 및 일부사용매개 변수, 위의 첫 번째 예에서와 같이 기능적으로는 직접 토토 캔 작성pl/pgsql및 교체 허용pl/pgsql변수가 발생합니다 자동으로. 중요한 차이점은execute각 실행에 대한 토토 캔을 다시 계획하고, 현재 매개 변수 값에 특정한 계획을 생성합니다. 반면pl/pgsql그렇지 않으면 일반 계획을 작성하고 재사용을 위해 캐시하십시오. 어디에서 최상의 계획은 매개 변수 값에 크게 의존합니다. 사용하는 데 도움이execute긍정적으로 일반 계획이 선택되지 않도록하십시오.

현재 지원되지 않습니다 이내에execute; 대신, 평범한 실행select토토 캔 및 지정in의 일부로execute자체.

참고 :thepl/pgsql execute진술은와 관련이 없습니다토토 결과 : 문서 : 9.3 : executeSQL 명령문이 지원합니다 그만큼PostgreSQL서버. 그만큼 서버execute명령문을 사용할 수 없습니다 직접PL/PGSQL함수 (그리고 필요하지 않습니다).

예 40-1. 동적 쿼리의 값 인용

동적 명령으로 작업 할 때 종종 처리해야합니다. 단일 따옴표의 탈출. 고정 인용 권장 방법 기능 본문의 텍스트는 달러 인용입니다. (유산이있는 경우 달러 견적을 사용하지 않는 코드는 개요를 참조하십시오. 안에섹션 40.11.1, 번역 할 때 약간의 노력을 절약 할 수 있습니다. 보다 합리적인 계획으로 코드.)

구성에 삽입 될 동적 값 쿼리는 자체적으로 포함 할 수 있으므로 신중한 취급이 필요합니다 인용 문자. 예제 (이것은 당신이 사용하고 있다고 가정합니다 기능 전체에 대한 달러 인용이므로 인용 표시가 필요합니다. 두 배가되지 않음) :

실행 'TBL 세트 업데이트'
        || quote_ident (colname)
        || '='
        || quote_literal (newValue)
        || 'key ='
        || quote_literal (keyvalue);

이 예제는의 사용을 보여줍니다.QUOTE_INDENandQUOTE_LITERAL함수 (참조섹션 9.4). 안전, 표현 함유 된 열 또는 테이블 식별자를 통과해야합니다QUOTE_INDENa 동적 쿼리. 문자 그대로 있어야하는 값을 포함하는 표현 구성 명령의 문자열은 통과해야합니다QUOTE_LITERAL. 이러한 기능은 사용됩니다 두 배로 동봉 된 입력 텍스트를 반환하기위한 적절한 단계 또는 임의의 내장 특수 문자와 함께 각각 단일 따옴표 제대로 탈출.

왜냐하면QUOTE_LITERAL라벨이 표시엄격한, 항상 null을 반환합니다 널 주장으로 불렀습니다. 위의 예에서 ifNewValue또는KeyValueNULL, 전체 동적 쿼리 문자열이 NULL이되어 의 오류execute. 당신은 이것을 피할 수 있습니다 를 사용하여 문제QUOTE_NULLABLE함수는와 동일하게 작동합니다QUOTE_LITERALnull과 함께 호출 할 때를 제외하고 인수는 문자열을 반환합니다NULL. 을 위한 예,

실행 'TBL 세트 업데이트'
        || quote_ident (colname)
        || '='
        || quote_nullable (newValue)
        || 'key ='
        || quote_nullable (keyvalue);

null 일 수있는 값을 다루는 경우 일반적으로 사용QUOTE_NULLABLE제자리에 의QUOTE_LITERAL.

항상 그렇듯이, 널 값을 쿼리는 의도하지 않은 결과를 제공하지 않습니다. 예를 들어여기서

'여기서 키 ='|| quote_nullable (keyvalue)

if 성공하지 못할 것입니다.KeyValue평등 연산자 사용 결과=null 피연산자가있는 것은 항상 null입니다. 당신이 원한다면 널 일반적인 키 가치처럼 작동하려면 다시 작성해야합니다. 위의 as

'키가'|| quote_nullable (keyvalue)

(현재,is 보다 훨씬 덜 효율적으로 처리=, SO 당신이 필수적이지 않으면 그렇게하지 마십시오. 보다섹션 9.2자세한 내용은 널 및뚜렷한.)

달러 인용은 고정 텍스트를 인용하는 데만 유용합니다. 이 예제를 다음과 같이 쓰려고 시도하는 것은 매우 나쁜 생각입니다.

실행 'TBL 세트 업데이트'
        || quote_ident (colname)
        || '= $$'
        || NewValue
        || '$$ key ='
        || quote_literal (keyvalue);

의 내용이 끊어지기 때문에NewValue함유$$. 같은 반대는 다른 반대에 적용됩니다 당신이 선택할 수있는 달러 인용 분리기. 따라서 텍스트를 안전하게 인용합니다 미리 알려지지 않았습니다.필수usequote_literal, QUOTE_NULLABLE또는QUOTE_INDEN, 적절하게.

동적 SQL 문은를 사용하여 안전하게 구성 할 수 있습니다형식함수 (참조섹션 9.4). 예를 들어:

Execute Format ( 'TBL 세트 %i = %l 여기서 key = %l', colname, newValue, keyValue);

the형식함수를 사용할 수 있습니다 와 함께사용절 :

형식 실행 ( 'TBL 세트 업데이트 %i = $ 1 key = $ 2', colname)
   NewValue 사용, keyValue;

이 양식은 매개 변수이기 때문에 더 효율적입니다.NewValueKeyValue텍스트로 변환되지 않았습니다.

동적 토토 캔의 훨씬 더 큰 예와execute예 40-9a를 구축하고 실행합니다.기능 생성새 함수를 정의하려는 토토 캔.

40.5.5. 결과를 얻습니다 상태

명령의 효과를 결정하는 몇 가지 방법이 있습니다. 그만큼 첫 번째 방법은를 사용하는 것입니다.진단 받기토토 캔, 양식이있는 토토 캔 :

get [current] 진단변수=항목[ , ... ];

이 토토 캔은 시스템 상태 표시기를 검색 할 수 있습니다. 각항목| 식별하는 핵심 단어입니다 지정된 변수에 할당 할 상태 값 ( 이를 수신하기에 적합한 데이터 유형이어야합니다). 현재 사용 가능합니다 상태 항목은row_count, 숫자 마지막으로 처리 된 행SQL토토 캔으로 전송SQL엔진, 그리고result_oid, 마지막 행의 OID 가장 최근에 삽입SQL토토 캔. 참고result_oid전용입니다 다음에 유용삽입Oids가 포함 된 테이블

예 :

진단 받기 integer_var = row_count;

명령의 효과를 결정하는 두 번째 방법은 이름이 지정된 특수 변수 확인발견, 유형의부울. 발견각각 내에서 거짓을 시작합니다pl/pgsql함수 호출. 각각에 의해 설정됩니다 다음 유형의 진술 :

  • a선택명세서 세트발견행이 할당 된 경우 true 행이없는 경우 False 반품.

  • a공연진술 세트발견하나 이상을 생성하고 폐기하는 경우 True 행, 행이 생성되지 않으면 거짓.

  • 업데이트, 삽입삭제진술 세트발견적어도 하나라면 참 행에 영향을 미치고, 행에 영향을 미치지 않으면 거짓.

  • afetch토토 캔문 세트발견행을 반환하는 경우 True, 행이없는 경우 False 반품.

  • a움직임진술 세트발견그것이 성공적으로 재배치하는 경우 커서, 그렇지 않으면 거짓.

  • afor또는foreach진술 세트발견하나 이상을 반복하면 그렇습니다 거짓.발견루프 일 때이 방식으로 설정됩니다 출구; 루프 실행 내부에서발견루프 토토 캔문에 의해 수정되지 않았습니다. 다른 진술의 실행에 의해 변경 될 수 있지만 루프 바디 내에서.

  • return queryandreturn query execute진술 세트발견쿼리가 하나 이상의 행을 반환하는 경우 true 행이 반환되지 않으면 false.

기타pl/pgsql진술 상태를 바꾸지 않음발견. 참고 특히execute출력을 변경합니다 의진단 받기그러나 변경되지는 않습니다발견.

발견각각의 로컬 변수입니다pl/pgsql함수; 변경 사항 그것은 현재 함수에만 영향을 미칩니다.

40.5.6. 전혀 아무것도하지 않는다

때로는 아무것도하지 않는 자리 표시 자 진술이 유용합니다. 예를 들어, if/when/else 체인의 한쪽 팔이 있음을 나타낼 수 있습니다. 의도적으로 비어 있습니다. 이 목적을 위해 사용하십시오.NULL진술 :

null;

예를 들어 다음 두 조각의 코드 조각입니다 동등한:

시작
    Y : = x / 0;
예외
    Division_by_zero가있을 때
        널;  - 오류를 무시하십시오
끝;
시작
    Y : = x / 0;
예외
    Division_By_Zero 일 때 - 오류를 무시하십시오
끝;

바람직한 맛의 문제입니다.

참고 :Oracle의 PL/SQL에서 빈 명령문 목록은 아닙니다 허용 및 soNULL진술은필수상황 이과 같은.PL/PGSQL허용합니다 대신 아무것도 쓰지 않으려면