윈 토토 구조가 아마도 가장 유용할 것입니다(그리고 중요) 일부PL/pgSQL. 와 함께PL/pgSQL의 통제 구조를 조작할 수 있습니다.포스트그레SQL매우 유연하고 강력한 방법입니다.
귀하가 복귀할 수 있는 두 가지 명령이 있습니다 함수의 데이터:반환그리고다음으로 돌아가기.
반환표현;
반환표현식 포함 함수를 종료하고 값을 반환합니다.표현발신자에게. 이 양식은 에 사용됩니다PL/pgSQL세트를 반환하지 않는 함수.
스칼라 유형을 반환할 때 모든 표현식을 사용할 수 있습니다. 표현식의 결과는 자동으로 할당에 대해 설명한 함수의 반환 유형입니다. 받는 사람 복합(행) 값을 반환하려면 레코드를 작성해야 합니다. 행 변수를표현.
함수의 반환 값은 정의되지 않은 상태로 둘 수 없습니다. 제어권이 최상위 블록의 끝에 도달한 경우 a를 누르지 않고 함수를 작동합니다.반환문, 런타임 오류가 발생합니다.
반환할 함수를 선언한 경우무효, 아반환문장 여전히 제공되어야 합니다. 하지만 이 경우 표현식은 다음반환선택사항이며 존재하는 경우 무시됩니다.
다음으로 돌아가기표현;
때PL/pgSQL함수 복귀가 선언되었습니다SETOF어떤 종류, 따라야 할 절차 약간 다릅니다. 이 경우 개별 항목은 반환은에 지정됩니다.다음으로 돌아가기명령, 그리고 마지막반환13699_13801반환 다음스칼라 데이터와 복합 데이터 모두에 사용할 수 있습니다. 유형; 후자의 경우 전체"테이블"의 결과가 반환됩니다.
사용하는 함수다음으로 돌아가기다음과 같은 방식으로 호출되어야 합니다:
SELECT * some_func()에서;
즉, 함수는 테이블 소스로 사용되어야 합니다.발신절.
다음으로 돌아가기실제로는 그렇지 않습니다 함수에서 복귀합니다. 그것은 단순히 가치를 저장합니다 표현. 그런 다음 실행은 다음으로 계속됩니다. 의 진술PL/pgSQL함수. 연속적으로다음으로 돌아가기명령이 실행되면 결과 세트가 구축됩니다. 결승전반환인수를 사용하면 윈 토토가 함수를 종료하게 됩니다.
참고:현재 구현다음으로 돌아가기forPL/pgSQL전체 결과를 저장합니다 설명한 대로 함수에서 반환되기 전에 설정합니다. 위. 즉, 만약 aPL/pgSQL함수는 매우 결과 집합이 크면 성능이 저하될 수 있습니다. 데이터가 메모리 고갈을 피하기 위해 디스크에 기록되지만 함수 자체는 전체 결과가 나올 때까지 반환되지 않습니다. 세트가 생성되었습니다. 다음 버전의PL/pgSQL사용자가 다음을 정의하도록 허용할 수 있습니다. 이러한 제한이 없는 집합 반환 함수입니다. 현재 데이터가 기록되기 시작하는 시점 디스크에 대한 제어는work_mem구성 변수. 더 큰 용량을 저장할 수 있는 충분한 메모리가 있는 관리자 메모리의 결과 집합은 이 값을 늘리는 것을 고려해야 합니다. 매개변수입니다.
IF문을 사용하면 실행할 수 있습니다. 특정 조건에 따른 명령입니다.PL/pgSQL5가지 형태가 있습니다IF:
만약 ... 그렇다면
만약 ... 그렇다면 ... ELSE
IF ... THEN ... ELSE IF
만약 ... 그렇다면 ... ELSIF ... 그렇다면 ... 그 외
만약 ... 그렇다면 ... ELSEIF ... 그렇다면 ... 그 외
IF부울 표현식그때문장END IF;
IF-THEN문장은 가장 간단한 형태의IF. 진술 사이그때그리고END IF조건이 다음과 같으면 실행됩니다. 사실. 그렇지 않으면 건너뜁니다.
예:
IF v_user_id < 0 THEN
사용자 업데이트 SET email = v_email WHERE user_id = v_user_id;
종료하면;
IF부울 표현식그때문장ELSE문장END IF;
IF-THEN-ELSE문 추가IF-THEN지정할 수 있게 하여 다음과 같은 경우 실행되어야 하는 대체 명령문 세트 조건이 false로 평가됩니다.
예:
IF parentid가 NULL이거나 parentid = ''
그런 다음
RETURN 전체 이름;
그 외
RETURN hp_true_filename(부모 ID) || '/' || 성명;
종료하면;
IF v_count 0 THEN
INSERT INTO users_count(개수) VALUES(v_count);
't'를 반환합니다.
그 외
'f'를 반환합니다.
종료하면;
IF문은 다음과 같이 중첩될 수 있습니다. 다음 예에서는:
IF deco_row.sex = 'm' THEN
Pretty_sex := '남자';
그 외
IF deco_row.sex = 'f' 그러면
Pretty_sex := '여자';
종료하면;
종료하면;
이 양식을 사용하면 실제로 중첩됩니다.IF내부 진술ELSE외부의 일부IF성명. 따라서 하나가 필요합니다.END IF중첩된 각 명령문IF그리고 하나는 부모용IF-ELSE. 이것은 실행 가능하지만 지루해집니다. 확인할 대안이 많을 때. 따라서 다음 양식.
IF부울 표현식그때진술 [ELSIF부울 표현식그때진술 [ELSIF부울 표현식그때성명 ...]] [ELSE성명 ] 종료하면;
IF-THEN-ELSIF-ELSE제공 여러 대안을 한 번에 확인하는 보다 편리한 방법 성명. 공식적으로는 중첩과 동일합니다.IF-THEN-ELSE-IF-THEN명령은 하나뿐임END IF필요합니다.
다음은 예입니다:
IF 숫자 = 0 THEN
결과 := '0';
ELSIF 번호 0 THEN
결과 := '긍정적';
ELSIF 숫자 < 0 THEN
결과 := '부정';
그 외
-- 흠, 유일한 다른 가능성은 숫자가 null이라는 것입니다.
결과 := 'NULL';
종료하면;
ELSEIF는의 별칭입니다.ELSIF.
와 함께윈 토토, 종료, 동안및for문장을 준비할 수 있습니다. 당신의PL/pgSQL기능 일련의 명령을 반복하십시오.
[<<라벨]
윈 토토문장END LOOP;
윈 토토무조건을 정의합니다. 에 의해 종료될 때까지 무한 반복되는 윈 토토종료또는반환성명. 선택적 라벨은 다음과 같습니다. 에서 사용됨종료중첩된 문 중첩 수준을 지정하는 윈 토토 종료되었습니다.
종료 [ 라벨 ] [언제표현 ];
아니면라벨주어지면, 가장 안쪽 윈 토토가 종료되고 다음 명령문이 나옵니다.END LOOP다음에 실행됩니다. 만일라벨주어진 것이어야 합니다. 현재 또는 중첩 윈 토토의 외부 수준의 레이블 또는 차단. 그런 다음 명명된 윈 토토나 블록이 종료되고 윈 토토/블록 다음의 명령문으로 제어가 계속됩니다. 해당END.
만약언제존재, 윈 토토 종료 지정된 조건이 true인 경우에만 발생하고, 그렇지 않으면 제어는 다음 명령문으로 전달됩니다.종료.
종료조기 발생에 사용될 수 있습니다. 모든 유형의 윈 토토를 종료합니다. 다음과 함께 사용하도록 제한되지 않습니다. 무조건 윈 토토.
예:
윈 토토
-- 일부 계산
IF 개수 0 그러면
종료; -- 윈 토토 종료
종료하면;
엔드 윈 토토;
윈 토토
-- 일부 계산
개수 0일 때 종료합니다. -- 이전 예제와 동일한 결과
엔드 윈 토토;
시작
-- 일부 계산
IF 주식 100000 THEN
종료; -- BEGIN 블록을 종료합니다.
종료하면;
끝;
[<<라벨]
동안표현윈 토토문장END LOOP;
그동안문은 다음을 반복합니다. 조건 표현식이 포함된 일련의 명령문 사실로 평가됩니다. 조건은 각 직전에 확인됩니다. 윈 토토 본문에 진입합니다.
예:
채무 금액 0 AND 선물_증명서 잔액 0 LOOP인 동안
-- 여기에 몇 가지 계산이 있습니다.
엔드 윈 토토;
boolean_expression LOOP가 아닌 동안
-- 여기에 몇 가지 계산이 있습니다.
끝 윈 토토;
[<<라벨] 에 대한이름IN [반전] 표현 .. 표현윈 토토문장END LOOP;
이 형태는for윈 토토를 생성합니다 이는 정수 값의 범위를 반복합니다. 변수이름자동으로 정의됩니다. 유형으로정수그리고 내부에만 존재합니다 윈 토토. 하한과 상한을 나타내는 두 가지 표현 범위의 경계는 윈 토토에 들어갈 때 한 번 평가됩니다. 반복 단계는 일반적으로 1이지만 다음과 같은 경우에는 -1입니다.반전지정되었습니다.
정수의 몇 가지 예for윈 토토:
i IN 1..10 윈 토토용
-- 여기에 몇 가지 계산이 있습니다.
인상 알림 'i는 %'입니다., i;
엔드 윈 토토;
역방향 10..1 윈 토토의 i용
-- 여기에 몇 가지 계산이 있습니다.
끝 윈 토토;
하한이 상한보다 큰 경우(또는 미만, 에서반전케이스), 윈 토토 본문이 전혀 실행되지 않습니다. 오류가 발생하지 않습니다.
다른 유형의 사용for윈 토토, 쿼리 결과를 반복하고 조작할 수 있습니다. 그에 따라 해당 데이터. 구문은 다음과 같습니다.
[<<라벨]
에 대한record_or_rowIN질의윈 토토문장END LOOP;
레코드 또는 행 변수는 각 행마다 연속적으로 할당됩니다. 의 결과질의(이것은 이어야 합니다.선택명령) 및 윈 토토 본문은 각 행에 대해 실행됩니다. 예는 다음과 같습니다.
CREATE FUNCTION cs_refresh_mviews() 정수를 $$로 반환합니다.
선언
mviews 기록;
시작
PERFORM cs_log('구체화된 뷰를 새로 고치는 중...');
FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP
-- 이제 "mviews"에는 cs_materialized_views의 레코드가 하나 있습니다.
PERFORM cs_log('구체화된 뷰 새로 고침' || quote_ident(mviews.mv_name) || ' ...');
'TRUNCATE TABLE' 실행 || quote_ident(mviews.mv_name);
'INSERT INTO' 실행 || quote_ident(mviews.mv_name) || ' ' || mviews.mv_query;
엔드 윈 토토;
PERFORM cs_log('구체화된 뷰 새로 고침이 완료되었습니다.');
1을 반환합니다.
끝;
$$ 언어 plpgsql;
윈 토토가 다음에 의해 종료되는 경우종료문, 마지막으로 할당된 행 값은 다음과 같습니다. 윈 토토 후에도 여전히 액세스 가능합니다.
그실행 중문은 다음과 같습니다 행을 반복하는 또 다른 방법:
[<<라벨]
에 대한record_or_row실행 중텍스트 표현윈 토토문장END LOOP;
이것은 소스를 제외하고 이전 양식과 같습니다선택문은 다음과 같이 지정됩니다. 각 항목에서 평가되고 다시 계획되는 문자열 표현식 에 입장for윈 토토. 이를 통해 프로그래머는 미리 계획된 쿼리의 속도를 선택하거나 일반 쿼리와 마찬가지로 동적 쿼리의 유연성실행진술.
참고:그PL/pgSQL파서 현재 두 종류를 구별합니다.for다음 여부를 확인하여 윈 토토(정수 또는 쿼리 결과)..괄호 밖에 나타남 사이IN그리고윈 토토. 만일..아님 그러면 윈 토토는 행에 대한 윈 토토인 것으로 추정됩니다. 잘못 입력함..그러므로 가능성이 높습니다 다음과 같은 불만 사항이 제기됩니다."행에 대한 윈 토토의 윈 토토 변수는 레코드여야 합니다. 또는 행 변수", 단순한 구문이 아닌 오류가 발생할 것으로 예상할 수 있습니다.
기본적으로 a에서 발생하는 모든 오류는PL/pgSQL함수가 실행을 중단합니다. 기능, 실제로 주변 거래도 마찬가지입니다. 다음을 사용하여 오류를 포착하고 복구할 수 있습니다.시작다음으로 차단예외절. 구문은 다음의 확장입니다. a의 일반 구문시작차단:
[ <<라벨 ] [선언선언 ] 시작문장예외 언제조건 [또는조건 ... ] 그러면handler_statements [언제조건 [또는조건 ... ] 그런 다음handler_statements ... ] 끝;
오류가 발생하지 않으면 이 블록 형식은 단순히 모든 항목을 실행합니다.문장, 그리고 제어는 다음 명령문으로 전달됩니다.END. 그러나 내에서 오류가 발생하면문장, 추가 처리 의문장버려졌고, 윈 토토는예외목록. 목록이 처음으로 검색됩니다.조건다음 오류와 일치합니다. 발생했습니다. 일치하는 항목이 발견되면 해당handler_statements실행된 다음 제어는 다음 명령문으로 전달됩니다.END. 일치하는 항목이 없으면 오류가 전파됩니다. 마치예외절 전혀 없었습니다. 오류는 둘러싸서 잡을 수 있습니다. 다음으로 차단예외또는 있는 경우 없음 함수 처리를 중단합니다.
그조건이름은 다음과 같을 수 있습니다 다음 중 하나에 표시됨Postgre메이저 토토 사이트 : 문서 : 8.0 : Postgre메이저 토토 사이트 오류 코드. 카테고리 이름은 해당 카테고리 내의 모든 오류와 일치합니다. 특수 조건 이름기타다음을 제외한 모든 오류 유형과 일치QUERY_CANCELED. (가능하지만 종종 현명하지 못한, 함정에 빠뜨리다QUERY_CANCELED작성자 이름.) 조건 이름은 대소문자를 구분하지 않습니다.
선택한 항목 내에서 새로운 오류가 발생하는 경우handler_statements, 잡을 수 없습니다 이것으로예외절이지만 전파되었습니다. 주변예외절이 그것을 잡을 수 있습니다.
에 의해 오류가 발견된 경우예외절, 지역 변수PL/pgSQL함수는 다음과 같이 유지됩니다. 오류가 발생한 시점이었지만 모든 변경 사항은 블록 내의 영구 데이터베이스 상태가 롤백됩니다. 다음과 같이 예를 들어 다음 조각을 고려해보세요.
INSERT INTO mytab(이름, 성) VALUES('톰', '존스');
시작
업데이트 mytab SET 이름 = 'Joe' WHERE 성 = 'Jones';
x := x + 1;
y := x / 0;
예외
WHEN Division_by_zero THEN
RAISE NOTICE 'divation_by_zero를 포착함';
반환 x;
끝;
통제가 다음에 대한 할당에 도달할 때y, 다음과 함께 실패합니다.division_by_zero오류. 이건 잡히겠지예외절. 가치 에서 반환됨반환문은 의 증가된 값이 됩니다.x하지만 의 효과업데이트명령은 롤백되었습니다.삽입34213_34329톰 존스아님조 존스.
팁:다음을 포함하는 블록예외절이 훨씬 더 많습니다. 블록이 없는 블록보다 들어가고 나가는 데 비용이 많이 듭니다. 그러므로 사용하지 마십시오.예외필요 없이.
예 35-1. 의 예외업데이트/삽입
이 예에서는 다음 중 하나를 수행하기 위해 예외 처리를 사용합니다.업데이트또는삽입적절하게.
CREATE TABLE db(INT 기본 키, b TEXT);
CREATE FUNCTION merge_db(key INT, data TEXT) VOID AS를 반환합니다.
$$
시작
윈 토토
업데이트 db SET b = 데이터 WHERE a = 키;
그렇다면 발견되면
반환;
종료하면;
시작
INSERT INTO db(a,b) VALUES(키, 데이터);
반품;
고유한 위반이 발생한 경우 예외
-- 아무것도 하지 마세요
끝;
엔드 윈 토토;
끝;
$$
언어 plpgsql;
SELECT merge_db(1, '데이비드');
SELECT merge_db(1, '데니스');