윈 토토 : 문서 : 9.4 : 윈 토토 | |||
---|---|---|---|
젠 토토 : 문서 : 9.4 : 표현식 | 와이즈 토토 : 문서 : 9.4 : PL/PGSQL -SQL 절차 언어 | 40 장pl/pgsql - SQL절차 언어 | 다음 |
이 섹션과 다음 섹션에서는에 의해 명시 적으로 이해되는 모든 진술 유형을 설명합니다.pl/pgsql. 이러한 사설 토토문 유형 중 하나로 인식되지 않은 것은 SQL 사설 토토으로 추정되며에 설명 된대로 실행하기 위해 기본 데이터베이스 엔진으로 전송됩니다.섹션 40.5.2and섹션 40.5.3.
값의 할당pl/pgsql변수는 다음과 같이 작성되었습니다.
변수 { := | = } 표현;
앞에서 설명한 바와 같이, 그러한 진술의 표현은 SQL을 통해 평가됩니다.select사설 토토은 기본 데이터베이스 엔진으로 전송됩니다. 표현식은 단일 값을 산출해야합니다 (변수가 행 또는 레코드 변수 인 경우 행 값 일 수 있음). 대상 변수는 간단한 변수 (선택적으로 블록 이름으로 자격이있는), 행 또는 레코드 변수 필드 또는 간단한 변수 또는 필드 인 배열 요소 일 수 있습니다. 동일한 (=) PL/SQL 호환 대신 사용할 수 있습니다:=.
표현식의 결과 데이터 유형이 변수의 데이터 유형과 일치하지 않거나 변수에 특정 크기/정밀도가 있습니다 (좋아요char (20)), 결과 값은에 의해 암시 적으로 변환됩니다.pl/pgsql결과 유형의 출력 기능 및 변수 유형의 입력 기능을 사용한 통역사. 결과 값의 문자열 양식이 입력 함수에 허용되지 않는 경우 입력 함수에 의해 생성 된 런타임 오류가 발생할 수 있습니다..
예 :
세금 : = 하위 토탈 * 0.06; my_record.user_id : = 20;
예를 들어 행을 반환하지 않는 SQL 사설 토토의 경우삽입a반환조항, a 내 사설 토토을 실행할 수 있습니다.PL/PGSQL사설 토토을 작성하는 것만으로 기능합니다.
anypl/pgsql사설 토토 텍스트에 나타나는 변수 이름은 매개 변수로 취급 된 다음 변수의 현재 값이 실행 시간에 매개 변수 값으로 제공됩니다. 이것은 표현에 대해 앞에서 설명한 처리와 똑같습니다. 자세한 내용은 참조섹션 40.10.1.
이러한 방식으로 SQL 사설 토토을 실행할 때pl/pgsql에서 논의 된대로 사설 토토에 대한 실행 계획을 캐시하고 재사용 할 수 있습니다.섹션 40.10.2.
때로는 표현식 또는를 평가하는 것이 유용합니다.select쿼리 그러나 결과를 버리십시오. 예를 들어 부작용이 있지만 유용한 결과 값이없는 함수를 호출 할 때.pl/pgsql, 사용공연진술 :
공연쿼리;
이것은 실행쿼리결과를 버립니다. 쓰기쿼리SQL을 작성하는 것과 같은 방식select사설 토토이지만 초기 키워드를 대체selectwith공연. 을 위한with쿼리, 사용공연그런 다음 쿼리를 괄호 안에 놓습니다. (이 경우 쿼리는 한 행만 반환 할 수 있습니다.)PL/PGSQL변수는 결과를 반환하지 않는 사설 토토과 마찬가지로 쿼리로 대체되며 계획은 같은 방식으로 캐시됩니다. 또한 특수 변수발견쿼리가 적어도 하나의 행을 생성 한 경우, 또는 행이 생성되지 않은 경우 False (참조섹션 40.5.5).
참고 :그 글쓰기를 기대할 수 있습니다select직접이 결과를 달성 할 것이지만 현재로서는 유일하게 받아 들여진 방법은공연. 와 같은 행을 반환 할 수있는 SQL 사설 토토select,가없는 한 오류로 거부됩니다.in다음 섹션에서 논의 된 절의 조항.
예 :
create_mv ( 'cs_session_page_requests_mv', my_query); 수행
SQL 사설 토토의 결과 단일 행 (여러 열의 가능성)을 산출하는 결과는 레코드 변수, 행 유형 변수 또는 스칼라 변수 목록에 할당 될 수 있습니다. 이것은 기본 SQL 사설 토토을 작성하고 추가를 추가하여 수행됩니다.into절. 예를 들어,
selectselect_expressions[에엄격한] 대상에서 ...; 삽입 ... 반환표현[에엄격한] 대상; 업데이트 ... 반환표현[에엄격한] 대상; 삭제 ... 반환표현[ 내엄격한] 대상;
여기서대상레코드 변수, 행 변수 또는 간단한 변수 및 레코드/행 필드의 쉼표로 구분 된 목록이 될 수 있습니다.pl/pgsql변수는 쿼리의 나머지 부분으로 대체되며 계획은 행을 반환하지 않는 사설 토토에 대해 위에서 설명한대로 캐시됩니다. 이것은 |select, 삽입/업데이트/삭제with반환및 ROW 세트 결과를 반환하는 유틸리티 사설 토토 (예 :설명). 을 제외하고in조항, SQL 사설 토토은 외부에 기록 될 것과 동일합니다pl/pgsql.
팁 :이 해석에 주목하십시오.selectwithinto|PostgreSQL'S Regement선택사설 토토, 여기서in대상은 새로 생성 된 테이블입니다. a에서 테이블을 만들고 싶다면select내부의 결과pl/pgsql함수, 구문 사용테이블 작성 ... 선택.
행 또는 가변 목록이 대상으로 사용되면 쿼리의 결과 열은 숫자 및 데이터 유형과 관련하여 대상의 구조와 정확히 일치해야합니다. 그렇지 않으면 런타임 오류가 발생합니다. 레코드 변수가 대상이면 쿼리 결과 열의 행 유형에 자동으로 구성됩니다.
theinto조항은 SQL 사설 토토의 거의 모든 곳에 표시 될 수 있습니다. 관습 적으로 그것은 | 목록 직전이나 바로 뒤에 쓰여졌다select_expressionsinselect사설 토토 또는 다른 사설 토토 유형에 대한 사설 토토의 끝에. 의 경우이 컨벤션을 준수하는 것이 좋습니다.pl/pgsql향후 버전에서 파서가 더 엄격 해집니다.
if엄격한에 지정되어 있지 않습니다.into조항,대상쿼리로 반환 된 첫 번째 행 또는 쿼리가 행이 반환되지 않은 경우 Nulls로 설정됩니다. ("첫 번째 줄"사용하지 않는 한 잘 정의되지 않았습니다주문 by.) 첫 번째 행 후 결과 행이 폐기됩니다. 스페셜을 확인할 수 있습니다발견변수 (참조섹션 40.5.5) 행이 반환되었는지 여부를 결정하려면 :
empname = myName에서 EMP에서 MyRec에 * 선택 *; 찾을 수없는 경우 예외 '직원 % 찾을 수 없음', MyName; 끝 If;
IF엄격한옵션이 지정되고 쿼리는 정확히 하나의 행을 반환해야합니다. 그렇지 않으면 런 타임 오류가보고됩니다.no_data_found(줄 없음) 또는TOO_MANY_ROWS(하나 이상). 예를 들어 오류를 잡으려는 경우 예외 블록을 사용할 수 있습니다 (예 :
시작 Empname = myName에서 Emp에서 Strict Myrec으로 * 선택하십시오. 예외 그렇다면 no_data_found 일 때 예외 '직원 % 찾을 수 없음', MyName; 언제 너무 _many_rows 예외를 제기하는 '직원 % 고유하지 않음', MyName; 끝;
사설 토토의 성공적인 실행엄격한항상 설정발견to true.
for삽입/업데이트/삭제with반환, pl/pgsql|엄격한지정되지 않았습니다. 와 같은 옵션이 없기 때문입니다.주문 by반환 해야하는 영향을받는 행을 결정하기 위해.
ifprint_strict_params함수에 대해 활성화되어 있으면 오류가 발생하면엄격한충족되지 않음,세부 사항오류 메시지의 일부에는 쿼리에 전달 된 매개 변수에 대한 정보가 포함됩니다. 당신은 변경할 수 있습니다print_strict_params설정으로 모든 기능 설정plpgsql.print_strict_params, 후속 기능 컴파일 만 영향을받지 만. 컴파일러 옵션을 사용하여 기능별로 활성화 할 수도 있습니다.
함수 만들기 get_userid (사용자 이름 텍스트) int를 반환합니다 $$로 #print_strict_params on 선언하다 userId int; 시작하다 사용자를 엄격한 userID로 선택하십시오 user.username = get_userid.username이있는 사용자로부터; 반환 userID; 끝 $$ 언어 plpgsql;
실패시이 함수는와 같은 오류 메시지를 생성 할 수 있습니다.
오류 : 쿼리는 행이 없습니다 세부 사항 : 매개 변수 : $ 1 = 'Nosuchuser' 컨텍스트 : pl/pgsql 함수 get_userid (텍스트) SQL 문 6 행
참고 :the엄격한옵션은 Oracle PL/SQL의 동작과 일치합니다선택및 관련 진술.
SQL 쿼리에서 여러 결과 행을 처리 해야하는 경우를 처리하려면 참조섹션 40.6.4.
종종 당신은 당신의 내부에서 동적 사설 토토을 생성하고 싶을 것입니다pl/pgsql함수, 즉 실행할 때마다 다른 테이블 또는 다른 데이터 유형이 포함되는 사설 토토.pl/pgsql의 사설 토토에 대한 계획을 캐시하려는 정상적인 시도 (섹션 40.10.2)는 그러한 시나리오에서 작동하지 않습니다. 이런 종류의 문제를 처리하려면execute진술이 제공됩니다 :
executeCommand-string [[ 내엄격한] 대상 ] [사용표현 [, ... ] ];
여기서Command-string(유형의 문자열을 산출하는 표현식입니다.텍스트) 실행 할 사설 토토을 포함합니다. 선택 사항대상는 레코드 변수, 행 변수 또는 간단한 변수 및 레코드/행 필드의 쉼표로 구분 된 목록입니다. 선택 사항사용사설 토토에 삽입 할 표현식 공급 값.
대체 없음PL/PGSQL변수는 계산 된 사설 토토 문자열에서 수행됩니다. 필요한 변수 값은 구성 될 때 사설 토토 문자열에 삽입해야합니다. 또는 아래에 설명 된대로 매개 변수를 사용할 수 있습니다.
또한,execute. 대신, 사설 토토문이 실행될 때마다 사설 토토은 항상 계획됩니다. 따라서 사설 토토 문자열은 기능 내에서 동적으로 생성되어 다른 테이블과 열에서 동작을 수행 할 수 있습니다.
thein조항은 SQL 사설 토토의 결과를 반환하는 행의 결과를 지정해야합니다. 행 또는 가변 목록이 제공되면 쿼리 결과의 구조와 정확히 일치해야합니다 (레코드 변수를 사용하는 경우 결과 구조와 자동으로 일치하도록 구성). 여러 행이 반환되면 첫 번째 행만에 할당됩니다.in변수. 행이 반환되지 않으면 NULL이에 할당됩니다.in변수. 그렇지 않은 경우into조항이 지정되어 있으며 쿼리 결과는 폐기됩니다.
인 경우엄격한옵션이 제공되며, 쿼리가 정확히 하나의 행을 생성하지 않는 한 오류 가보고됩니다.
사설 토토 문자열은 매개 변수 값을 사용할 수 있으며 사설 토토에$1, $2등.이 기호는에 제공된 값을 나타냅니다.사용절. 이 방법은 종종 텍스트로 사설 토토 문자열에 데이터 값을 삽입하는 것보다 선호됩니다. 값을 텍스트와 뒤로 변환하는 런 타임 오버 헤드를 피하며 인용 또는 이스케이프 할 필요가 없기 때문에 SQL 주입 공격에 훨씬 덜 걸립니다. 예는 다음과 같습니다.
execute '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.4 : executeSQL 사설 토토문에서 지원하는 SQL 사설 토토문postgresql서버. 서버의execute진술은 직접 사용할 수 없습니다PL/PGSQL기능 (필요하지 않음).
예 40-1. 동적 쿼리의 값 인용
동적 사설 토토으로 작업 할 때는 종종 단일 따옴표의 탈출을 처리해야합니다. 기능 본문에서 고정 텍스트를 인용하는 권장 방법은 달러 인용입니다. (달러 인용을 사용하지 않는 레거시 코드가있는 경우 개요를 참조하십시오.섹션 40.11.1, 해당 코드를보다 합리적인 체계로 번역 할 때 약간의 노력을 절약 할 수 있습니다.)
구성된 쿼리에 삽입 해야하는 동적 값은 인용 문자가 포함되어 있으므로 신중한 처리가 필요합니다. 예제 (이것은 당신이 함수에 대해 달러 인용문을 전체적으로 사용하고 있다고 가정하므로 견적 표시를 두 배로 늘릴 필요는 없습니다) :.
실행 'TBL 세트 업데이트' || quote_ident (colname) || '=' || quote_literal (newValue) || 'key =' || quote_literal (keyvalue);
이 예제는의 사용을 보여줍니다.QUOTE_INDEN
andquote_literal
함수 (참조PostgreSQL : 문서 : 9.4 : 스포츠 토토 함수 및 연산자). 안전을 위해 열 또는 테이블 식별자를 포함하는 표현식을 통과해야합니다quote_ident
동적 쿼리에 삽입하기 전에. 구성된 사설 토토에 문자 그대로 해야하는 값을 포함하는 표현식을 통과해야합니다QUOTE_LITERAL
. 이 기능은 각각 이중 또는 단일 따옴표로 둘러싸인 입력 텍스트를 반환하기 위해 적절한 단계를 수행하고 임베디드 특수 문자가 올바르게 탈출했습니다.
때문에QUOTE_LITERAL
라벨이 표시엄격한, null 인수로 호출되면 항상 null을 반환합니다. 위의 예에서 ifNewValue또는KeyValue무효가되었고, 전체 동적 쿼리 문자열이 널이되어 오류가 발생합니다.execute. 를 사용 하여이 문제를 피할 수 있습니다.QUOTE_NULLABLE
함수는와 동일하게 작동합니다.quote_literal
널 인수로 호출 할 때 문자열을 반환하는 것을 제외하고NULL. 예를 들어,
실행 'TBL 세트 업데이트' || quote_ident (colname) || '=' || quote_nullable (newValue) || 'key =' || quote_nullable (keyvalue);
null 일 수있는 값을 다루는 경우 일반적으로 사용해야합니다QUOTE_NULLABLE
대신quote_literal
.
항상 그렇듯이 쿼리의 널 값이 의도하지 않은 결과를 제공하지 않도록주의해야합니다. 예를 들어여기서절
'여기서 key ='|| quote_nullable (keyvalue)
IF 성공하지 못할 것입니다.KeyValue평등 연산자를 사용한 결과이기 때문에 null입니다.=널 피연산자가있는 것은 항상 널입니다. NULL이 일반적인 키 가치처럼 작동하기를 원한다면 위를 다시 작성해야합니다.
'키가'|| quote_nullable (keyvalue)
(현재,|보다 훨씬 덜 효율적으로 처리됩니다=, 따라서해야 할 경우를 제외하고는하지 마십시오. 보다PostgreSQL : 문서 : 9.4 : 비교 토토 핫nulls 및에 대한 자세한 내용은뚜렷하다.)
달러 인용은 고정 텍스트를 인용하는 데만 유용합니다. 이 예제를 다음과 같이 쓰려고 시도하는 것은 매우 나쁜 생각입니다.
실행 'TBL 세트 업데이트' || quote_ident (colname) || '= $$' || NewValue || '$$ key =' || quote_literal (keyvalue);
이면 끊어지기 때문에NewValue함유$$. 동일한 반대 의견은 선택할 수있는 다른 달러 인출 구분 기호에 적용됩니다. 따라서 미리 알려지지 않은 텍스트를 안전하게 인용하려면필수usequote_literal
, QUOTE_NULLABLE
, 또는QUOTE_INDEN
, 적절하게.
동적 SQL 문은를 사용하여 안전하게 구성 할 수 있습니다형식
함수 (참조PostgreSQL : 문서 : 9.4 : 스포츠 토토 함수 및 연산자). 예를 들어:
형식 실행 ( 'TBL 세트 %i = %l 여기서 key = %l', colname, newValue, keyValue);
the형식
함수는와 함께 사용할 수 있습니다.사용절 :
형식 실행 ( 'TBL 세트 업데이트 %i = $ 1 key = $ 2', colname) NewValue 사용, keyValue;
이 양식은 매개 변수이기 때문에 더 효율적입니다.NewValue및KeyValue텍스트로 변환되지 않습니다.
동적 사설 토토의 훨씬 더 큰 예와execute예 40-9, A를 구축하고 실행하는함수 만들기새 함수를 정의하는 사설 토토.
사설 토토의 효과를 결정하는 몇 가지 방법이 있습니다. 첫 번째 방법은를 사용하는 것입니다.진단 받기사설 토토, 양식이 있습니다.
get [현재] 진단변수 { = | := } 항목 [ , ... ];
이 사설 토토은 시스템 상태 표시기를 검색 할 수 있습니다.현재소음 단어입니다 (그러나 참조스택 진단 받기in섹션 40.6.6.1). 각항목지정된 상태 값을 식별하는 핵심 단어가변(이를 수신하기에 적합한 데이터 유형이어야 함). 현재 사용 가능한 상태 항목은에 표시됩니다.표 40-1. 결장 평등 (:=) SQL 표준 대신 사용할 수 있습니다=토큰. 예 :
진단 받기 integer_var = row_count;
표 40-1. 사용 가능한 진단 항목
이름 | 타입 | 설명 |
---|---|---|
row_count | 정수 | 가장 최근에 처리 된 행 수SQL사설 토토 |
result_oid | OID | 가장 최근에 삽입 된 마지막 행의 OIDSQL사설 토토 (AN 이후에만 유용삽입OID가있는 테이블에 사설 토토) |
PG_CONTEXT | 텍스트 | 현재 통화 스택을 설명하는 텍스트의 줄 (참조섹션 40.6.7) |
사설 토토의 효과를 결정하는 두 번째 방법은 명명 된 특수 변수를 확인하는 것입니다.발견, 유형의부울. 발견각각 내에서 거짓을 시작합니다pl/pgsql함수 호출. 다음 각 유형의 진술에 의해 설정됩니다.
A 성명서 세트발견행이 지정된 경우 true 행이 반환되지 않으면 false입니다.
A 공연성명서 세트발견하나 이상의 행을 생성하고 폐기하는 경우 true 행이 생성되지 않으면 거짓.
업데이트, 삽입및삭제진술 세트발견적어도 하나의 행에 영향을 미치는 경우, 행에 영향을 미치지 않으면 거짓.
A Fetch사설 토토문 세트발견행을 반환하는 경우 true 행이 반환되지 않으면 false입니다.
A 움직임사설 토토문 세트발견그것이 커서를 성공적으로 재배치하면 그렇지 않으면 false.
A for또는foreach진술 세트발견하나 이상을 반복하는 경우 true false.발견루프가 종료 될 때이 방식으로 설정됩니다. 루프 실행 내부에서발견루프 본문 내에서 다른 문의 실행에 의해 변경 될 수 있지만 루프 문에 의해 수정되지 않았다..
return query및반환 쿼리 실행진술 세트발견쿼리가 하나 이상의 행을 반환하는 경우, 행이 반환되지 않으면 거짓.
기타pl/pgsql진술은 상태를 변경하지 않습니다발견. 특히execute출력 변경진단 받기, 그러나 변경되지는 않습니다발견.
발견각각의 로컬 변수입니다PL/PGSQL함수; 그것에 대한 모든 변경 사항은 현재 함수에만 영향을 미칩니다.
때로는 아무것도하지 않는 자리 표시 자 진술이 유용합니다. 예를 들어, if/the/else 체인의 한 팔이 의도적으로 비어 있음을 나타낼 수 있습니다. 이 목적을 위해 사용하십시오.NULL진술 :
null;
예를 들어, 다음 두 조각의 코드 조각은 동일합니다.
시작 Y : = x / 0; 예외 Division_by_zero가있을 때 널; - 오류를 무시하십시오 끝;
시작 Y : = x / 0; 예외 Division_By_Zero 일 때 - 오류를 무시하십시오 끝;
바람직한 것은 맛의 문제입니다.
참고 :Oracle의 PL/SQL에서 빈 사설 토토문 목록은 허용되지 않습니다.NULL진술은필수이와 같은 상황의 경우.PL/PGSQL대신 아무것도 쓸 수 있습니다.