Postgresql 9.3.25 문서 | ||||
---|---|---|---|---|
PostgreSQL : 문서 : 9.3 : 토토 캔식 | Postgre메이저 토토 사이트 : 문서 : 9.3 : PL/PG메이저 토토 사이트 -메이저 토토 사이트 절차 언어 | 40 장pl/pgsql - SQL절차 언어 | 다음 |
이 섹션과 다음 섹션에서는 모든 것을 설명합니다. 명시 적으로 이해되는 진술 유형pl/pgsql. 하나로 인식되지 않은 것 이 진술 유형은 SQL 명령으로 추정되며 전송됩니다. 에 설명 된대로 실행할 기본 데이터베이스 엔진에섹션 40.5.2and섹션 40.5.3.
값의 할당pl/pgsql변수는 다음과 같이 작성되었습니다.
가변: =표현;
앞에서 설명한 바와 같이, 그러한 진술의 표현은 다음과 같습니다. SQL을 통해 평가select기본 데이터베이스 엔진으로 전송 된 명령. 표현은 생성해야합니다 단일 값 (변수가 행 인 경우 행 값일 수 있습니다. 레코드 변수). 대상 변수는 단순한 변수 일 수 있습니다 (선택적으로 블록 이름으로 자격이 있음), 행 필드 또는 레코드 변수 또는 간단한 배열 요소 변수 또는 필드.
표현식의 결과 데이터 유형이 일치하지 않는 경우 변수의 데이터 유형 또는 변수의 특정 크기/정밀도가 있습니다. (좋다char (20)), 결과 값이 될 것입니다 암시 적으로 변환pl/pgsql결과 유형을 사용한 통역사 출력 기능 및 변수 유형의 입력 기능. 주목하십시오 이로 인해 잠재적으로 런타임 오류가 발생할 수 있습니다. 입력 함수, 결과 값의 문자열 양식이 그렇지 않은 경우 입력 함수에 허용됩니다.
예 :
세금 : = 하위 토탈 * 0.06; my_record.user_id : = 20;
예를 들어 행을 반환하지 않는 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);
단일 행을 산출하는 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.
종종 내부에서 동적 토토 캔을 생성하고 싶을 것입니다 당신의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_INDEN
andQUOTE_LITERAL
함수 (참조섹션 9.4). 안전, 표현
함유 된 열 또는 테이블 식별자를 통과해야합니다QUOTE_INDEN
a
동적 쿼리. 문자 그대로 있어야하는 값을 포함하는 표현
구성 명령의 문자열은 통과해야합니다QUOTE_LITERAL
. 이러한 기능은 사용됩니다
두 배로 동봉 된 입력 텍스트를 반환하기위한 적절한 단계
또는 임의의 내장 특수 문자와 함께 각각 단일 따옴표
제대로 탈출.
왜냐하면QUOTE_LITERAL
라벨이 표시엄격한, 항상 null을 반환합니다
널 주장으로 불렀습니다. 위의 예에서 ifNewValue또는KeyValueNULL, 전체 동적 쿼리 문자열이 NULL이되어
의 오류execute. 당신은 이것을 피할 수 있습니다
를 사용하여 문제QUOTE_NULLABLE
함수는와 동일하게 작동합니다QUOTE_LITERAL
null과 함께 호출 할 때를 제외하고
인수는 문자열을 반환합니다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;
이 양식은 매개 변수이기 때문에 더 효율적입니다.NewValue및KeyValue텍스트로 변환되지 않았습니다.
동적 토토 캔의 훨씬 더 큰 예와execute예 40-9a를 구축하고 실행합니다.기능 생성새 함수를 정의하려는 토토 캔.
명령의 효과를 결정하는 몇 가지 방법이 있습니다. 그만큼 첫 번째 방법은를 사용하는 것입니다.진단 받기토토 캔, 양식이있는 토토 캔 :
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함수; 변경 사항 그것은 현재 함수에만 영향을 미칩니다.
때로는 아무것도하지 않는 자리 표시 자 진술이 유용합니다. 예를 들어, if/when/else 체인의 한쪽 팔이 있음을 나타낼 수 있습니다. 의도적으로 비어 있습니다. 이 목적을 위해 사용하십시오.NULL진술 :
null;
예를 들어 다음 두 조각의 코드 조각입니다 동등한:
시작 Y : = x / 0; 예외 Division_by_zero가있을 때 널; - 오류를 무시하십시오 끝;
시작 Y : = x / 0; 예외 Division_By_Zero 일 때 - 오류를 무시하십시오 끝;
바람직한 맛의 문제입니다.
참고 :Oracle의 PL/SQL에서 빈 명령문 목록은 아닙니다 허용 및 soNULL진술은필수상황 이과 같은.PL/PGSQL허용합니다 대신 아무것도 쓰지 않으려면