이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
다음에 대한 동일한 페이지를 보고 싶을 수도 있습니다.토토 사이트 PostgreSQL : 문서 : 17 : 41.6. 제어 구조버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

40.6. 토토 꽁 머니 구조

토토 꽁 머니 구조는 아마도 가장 유용하고 중요한 부분일 것입니다.PL/pgSQL. 와 함께PL/pgSQL의 토토 꽁 머니 구조를 조작할 수 있습니다.포스트그레SQL매우 유연하고 강력한 방식으로 데이터를 제공합니다.

40.6.1. 함수에서 복귀

함수에서 데이터를 반환하는 데 사용할 수 있는 두 가지 명령이 있습니다.반환그리고다음으로 돌아가기.

40.6.1.1. 반환

반환표현;

반환표현식을 사용하면 함수를 종료하고 값을 반환합니다.표현발신자에게. 이 양식은 다음 용도로 사용됩니다.PL/pgSQL세트를 반환하지 않는 함수.

스칼라 유형을 반환하는 함수에서 표현식의 결과는 할당에 대해 설명한 대로 자동으로 함수의 반환 유형으로 캐스팅됩니다. 그러나 복합(행) 값을 반환하려면 요청된 열 집합을 정확하게 전달하는 식을 작성해야 합니다. 명시적 캐스팅을 사용해야 할 수도 있습니다.

출력 매개변수를 사용하여 함수를 선언한 경우 다음과 같이 작성하세요.반환표현이 없습니다. 출력 매개변수 변수의 현재 값이 반환됩니다.

반환할 함수를 선언한 경우무효, 아반환문을 사용하여 함수를 일찍 종료할 수 있습니다. 하지만 다음과 같은 표현은 쓰지 마세요.반환.

함수의 반환 값은 정의되지 않은 상태로 둘 수 없습니다. 컨트롤이 a를 누르지 않고 함수의 최상위 블록 끝에 도달한 경우반환문을 작성하면 런타임 오류가 발생합니다. 이 제한은 출력 매개변수가 있는 함수와 반환하는 함수에는 적용되지 않습니다.공허13003_13033반환최상위 블록이 완료되면 문이 자동으로 실행됩니다.

일부 예:

-- 스칼라 유형을 반환하는 함수
1 + 2를 반환합니다.
반환 scalar_var;

-- 복합 유형을 반환하는 함수
RETURN 복합_유형_var;
RETURN (1, 2, '3'::텍스트);  -- 올바른 유형으로 열을 캐스팅해야 합니다.

40.6.1.2. 다음으로 돌아가기그리고반환 쿼리

다음으로 돌아가기표현;
반환 쿼리질의;
쿼리 실행 반환명령어-문자열 [사용 중표현 [, ... ] ];

PL/pgSQL함수가 반환되도록 선언되었습니다.SETOF어떤 종류, 따라야 할 절차가 약간 다릅니다. 이 경우 반환할 개별 항목은 다음 순서로 지정됩니다.다음으로 돌아가기또는반환 쿼리명령, 그리고 마지막반환인수가 없는 명령은 함수 실행이 완료되었음을 나타내는 데 사용됩니다.다음으로 돌아가기스칼라 및 복합 데이터 유형 모두에 사용할 수 있습니다. 복합 결과 유형, 전체"테이블"의 결과가 반환됩니다.반환 쿼리쿼리 실행 결과를 함수의 결과 세트에 추가합니다.다음으로 돌아가기그리고반환 쿼리은 단일 집합 반환 함수에서 자유롭게 혼합될 수 있으며, 이 경우 해당 결과는 연결됩니다.

다음으로 돌아가기그리고반환 쿼리실제로 함수에서 반환하지 않습니다. 단순히 함수의 결과 집합에 0개 이상의 행을 추가하기만 하면 됩니다. 그런 다음 실행은의 다음 문으로 계속됩니다.PL/pgSQL함수. 연속적으로다음으로 돌아가기또는반환 쿼리명령이 실행되면 결과 세트가 구축됩니다. 결승전반환15385_15516

반환 쿼리변형 있음반환 쿼리 실행, 동적으로 실행될 쿼리를 지정합니다. 매개변수 표현식은 다음을 통해 계산된 쿼리 문자열에 삽입될 수 있습니다.사용 중, 마찬가지로실행명령.

출력 매개변수를 사용하여 함수를 선언한 경우 다음과 같이 작성하세요.다음으로 돌아가기표현이 없습니다. 각 실행 시 출력 매개변수 변수의 현재 값은 최종 반환을 위해 결과 행으로 저장됩니다. 함수를 반환하도록 선언해야 합니다.SETOF 레코드여러 출력 매개변수가 있는 경우 또는SETOF어떤 유형유형의 출력 매개변수가 하나만 있는 경우어떤 유형, 출력 매개변수를 사용하여 집합 반환 함수를 생성하기 위해.

다음은 다음을 사용하는 함수의 예입니다.다음으로 돌아가기:

CREATE TABLE foo(foid INT, foosubid INT, fooname TEXT);
INSERT INTO foo VALUES (1, 2, '3');
foo 값에 삽입(4, 5, '6');

함수 생성 또는 교체 get_all_foo()는 SETOF foo AS를 반환합니다.
$BODY$
선언
    r foo%행유형;
시작
    r IN의 경우
        SELECT * FROM foo WHERE fooid  0
    토토 꽁 머니
        -- 여기에서 일부 처리를 수행할 수 있습니다.
        다음으로 돌아가기 r; -- SELECT의 현재 행을 반환합니다.
    엔드 토토 꽁 머니;
    반품;
종료
$BODY$
언어 plpgsql;

SELECT * FROM get_all_foo();

다음은 다음을 사용하는 함수의 예입니다.반환 쿼리:

CREATE FUNCTION get_available_flightid(date) SETOF 정수 AS를 반환합니다.
$BODY$
시작
    반환 쿼리 선택 항공편 ID
                   항공편 출발
                  비행 날짜 = $1인 곳
                    AND 항공편 날짜 < ($1 + 1);

    -- 실행이 완료되지 않았으므로 행이 반환되었는지 확인할 수 있습니다.
    -- 그렇지 않은 경우 예외를 발생시킵니다.
    발견되지 않은 경우
        RAISE EXEPTION '%.에 항공편 없음', $1;
    종료하면;

    반품;
 종료
$BODY$
언어 plpgsql;

-- 이용 가능한 항공편을 반환하거나 항공편이 없는 경우 예외 발생
-- 이용 가능한 항공편.
SELECT * FROM get_available_flightid(CURRENT_DATE);

참고:현재 구현다음으로 돌아가기그리고반환 쿼리위에서 설명한 대로 함수에서 반환되기 전에 전체 결과 세트를 저장합니다. 즉, 만약 aPL/pgSQL함수는 매우 큰 결과 집합을 생성하므로 성능이 저하될 수 있습니다. 메모리 고갈을 방지하기 위해 데이터가 디스크에 기록되지만 함수 자체는 전체 결과 집합이 생성될 때까지 반환되지 않습니다. 다음 버전의PL/pgSQL사용자는 이러한 제한이 없는 집합 반환 함수를 정의할 수 있습니다. 현재 데이터가 디스크에 기록되기 시작하는 지점은work_mem구성 변수. 더 큰 결과 세트를 메모리에 저장할 만큼 충분한 메모리가 있는 관리자는 이 매개변수를 늘리는 것을 고려해야 합니다.

40.6.2. 조건부

IF그리고사례문을 사용하면 특정 조건에 따라 대체 명령을 실행할 수 있습니다.PL/pgSQL세 가지 형태의가 있습니다.IF:

  • IF ... THEN ... END IF

  • IF ... THEN ... ELSE ... END IF

  • IF ... THEN ... ELSIF ... THEN ... ELSE ... END IF

그리고 두 가지 형태의사례:

  • CASE ... WHEN ... THEN ... ELSE ... END CASE

  • CASE WHEN ... THEN ... ELSE ... END CASE

40.6.2.1. IF-THEN

IF부울 표현식그때진술END IF;

IF-THEN문은 가장 간단한 형식입니다.IF. 사이의 진술그때그리고END IF조건이 true일 경우 실행됩니다. 그렇지 않으면 건너뜁니다.

예:

IF v_user_id < 0 THEN
    사용자 업데이트 SET email = v_email WHERE user_id = v_user_id;
종료하면;

40.6.2.2. IF-THEN-ELSE

IF부울 표현식그때문장ELSE문장END IF;

IF-THEN-ELSE문 추가IF-THEN조건이 참이 아닌 경우 실행되어야 하는 대체 명령문 세트를 지정할 수 있게 합니다. (여기에는 조건이 NULL로 평가되는 경우도 포함됩니다.)

예:

IF parentid가 NULL이거나 parentid = ''
그런 다음
    RETURN 전체 이름;
그 외
    RETURN hp_true_filename(부모 ID) || '/' || 성명;
종료하면;
IF v_count  0 THEN
    INSERT INTO users_count(개수) VALUES(v_count);
    't'를 반환합니다.
그 외
    'f'를 반환합니다.
종료하면;

40.6.2.3. IF-THEN-ELSIF

IF부울 표현식그때문장
[ELSIF부울 표현식그때문장
[ELSIF부울 표현식그때문장
    ...]]
[ELSE문장 ]
종료하면;

때때로 두 가지 이상의 대안이 있을 수 있습니다.IF-THEN-ELSIF여러 대안을 차례로 확인하는 편리한 방법을 제공합니다.IF조건은 참인 첫 번째 조건이 발견될 때까지 연속적으로 테스트됩니다. 그런 다음 관련 문이 실행되고 그 후 제어는 다음 문으로 전달됩니다.END IF. (모든 후속IF조건은아님테스트했습니다.) 다음 중 어느 것도 해당되지 않는 경우IF조건이 참이면ELSE블록(있는 경우)이 실행됩니다.

다음은 예입니다:

IF 숫자 = 0 THEN
    결과 := '0';
ELSIF 번호  0 THEN
    결과 := '긍정적';
ELSIF 숫자 < 0 THEN
    결과 := '부정';
그 외
    -- 흠, 유일한 다른 가능성은 숫자가 null이라는 것입니다.
    결과 := 'NULL';
종료하면;

핵심 단어ELSIF철자도 가능함ELSEIF.

동일한 작업을 수행하는 또 다른 방법은 중첩하는 것입니다.IF-THEN-ELSE문, 다음 예와 같이:

IF deco_row.sex = 'm' THEN
    Pretty_sex := '남자';
그 외
    IF deco_row.sex = 'f' 그러면
        Pretty_sex := '여자';
    종료하면;
종료하면;

그러나 이 방법은 일치하는 항목을 작성해야 합니다.END IF각각IF이므로 를 사용하는 것보다 훨씬 번거롭습니다.ELSIF대안이 많을 때.

40.6.2.4. 단순사례

사례검색 표현언제표현 [, 표현 [ ... ]] 그러면문장
  [언제표현 [, 표현 [ ... ]] 그러면문장
    ... ]
  [ELSE문장 ]
종료 사례;

간단한 형식사례피연산자의 동일성을 기반으로 조건부 실행을 제공합니다.검색 표현평가(한 번)되고 연속적으로 각각 비교됩니다.표현에서언제절. 일치하는 항목이 발견되면 해당하는문장실행된 후 제어는 다음 명령문으로 넘어갑니다.END CASE. (다음에)언제표현식은 평가되지 않습니다.) 일치하는 항목이 없으면ELSE 문장실행됩니다; 하지만 만약에ELSE존재하지 않는 경우 aCASE_NOT_FOUND예외가 발생했습니다.

다음은 간단한 예입니다:

사례 x
    1, 2일 때
        msg := '하나 또는 둘';
    그 외
        msg := '1 또는 2 이외의 값';
종료 사례;

40.6.2.5. 검색됨사례

사례
    언제부울 표현식그때문장
  [언제부울 표현식그때문장
    ... ]
  [ELSE문장 ]
종료 사례;

검색된 형태사례부울 표현식의 진실성을 기반으로 조건부 실행을 제공합니다. 각각언제절의부울 표현식결과가 나올 때까지 차례로 평가됩니다.. 그러면 해당문장실행된 후 제어는 다음 명령문으로 넘어갑니다.END CASE. (다음에)언제표현식은 평가되지 않습니다.) 참 결과가 발견되지 않으면,ELSE 문장실행됩니다. 하지만 만약에ELSE존재하지 않는 경우 aCASE_NOT_FOUND예외가 발생했습니다.

다음은 예입니다:

사례
    WHEN x 0과 10 사이 THEN
        msg := '값은 0과 10 사이입니다.';
    언제 x 11시와 20시 사이
        msg := '값은 11에서 20 사이입니다';
종료 사례;

이 형식은사례완전히 다음과 같습니다.IF-THEN-ELSIF, 생략된 도달 규칙 제외ELSE절은 아무것도 하지 않는 대신 오류를 발생시킵니다.

40.6.3. 단순 토토 꽁 머니

와 함께토토 꽁 머니, 종료, 계속, 동안, forFOREACH문장을 준비할 수 있습니다.PL/pgSQL일련의 명령을 반복하는 함수입니다.

40.6.3.1. 토토 꽁 머니

[ <<라벨 ]
토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

토토 꽁 머니에 의해 종료될 때까지 무기한 반복되는 무조건 토토 꽁 머니를 정의합니다.종료또는반환문장. 선택사항라벨다음에서 사용할 수 있습니다종료그리고계속중첩 토토 꽁 머니 내의 명령문을 사용하여 해당 명령문이 참조하는 토토 꽁 머니를 지정합니다.

40.6.3.2. 종료

종료 [ 라벨 ] [언제부울 표현식 ];

아니면라벨이 주어지면 가장 안쪽 토토 꽁 머니가 종료되고 다음 명령문이 나옵니다.END LOOP다음에 실행됩니다. 만일라벨이 주어지면 현재 또는 중첩 토토 꽁 머니나 블록의 일부 외부 수준의 레이블이어야 합니다. 그런 다음 명명된 토토 꽁 머니 또는 블록이 종료되고 토토 꽁 머니/블록의 해당 명령문 뒤의 명령문으로 제어가 계속됩니다.END.

만약언제이 지정되면 토토 꽁 머니 종료는 다음 경우에만 발생합니다.부울 표현식사실입니다. 그렇지 않으면 제어는 다음 문으로 전달됩니다.종료.

종료모든 유형의 토토 꽁 머니와 함께 사용할 수 있습니다. 무조건 토토 꽁 머니와 함께 사용하는 것으로 제한되지 않습니다.

a와 함께 사용하는 경우시작차단,종료블록 끝 이후의 다음 문으로 제어를 전달합니다. 이 목적을 위해서는 라벨을 사용해야 합니다. 라벨이 없는종료a와 일치하는 것으로 간주되지 않습니다.시작차단. (이는 8.4 이전 릴리스에서 변경된 사항입니다.PostgreSQL, 이는 라벨이 지정되지 않은종료a와 일치시키다시작차단합니다.)

예:

토토 꽁 머니
    -- 일부 계산
    IF 개수  0 그러면
        종료;  -- 토토 꽁 머니 종료
    종료하면;
엔드 토토 꽁 머니;

토토 꽁 머니
    -- 일부 계산
    개수  0일 때 종료합니다.  -- 이전 예제와 동일한 결과
엔드 토토 꽁 머니;

<<차단
시작
    -- 일부 계산
    IF 주식  100000 THEN
        EXIT 블록;  -- BEGIN 블록을 종료합니다.
    종료하면;
    -- 주식  100000인 경우 여기 계산은 건너뜁니다.
끝;

40.6.3.3. 계속

계속 [ 라벨 ] [언제부울 표현식 ];

아니면라벨이 주어지면 가장 안쪽 토토 꽁 머니의 다음 반복이 시작됩니다. 즉, 토토 꽁 머니 본문에 남아 있는 모든 문을 건너뛰고 제어가 토토 꽁 머니 제어 표현식(있는 경우)으로 반환되어 다른 토토 꽁 머니 반복이 필요한지 여부를 결정합니다. 만일라벨이 있으면 실행이 계속될 토토 꽁 머니의 레이블을 지정합니다.

만약언제이 지정되면 토토 꽁 머니의 다음 반복은 다음 경우에만 시작됩니다.부울 표현식사실입니다. 그렇지 않으면 제어는 다음 문으로 전달됩니다.계속.

계속모든 유형의 토토 꽁 머니와 함께 사용할 수 있습니다. 무조건 토토 꽁 머니와 함께 사용하는 것으로 제한되지 않습니다.

예:

토토 꽁 머니
    -- 일부 계산
    개수가 100보다 크면 종료합니다.
    개수가 50 미만일 때 계속하세요.
    -- 개수 IN [50 .. 100]에 대한 일부 계산
끝 토토 꽁 머니;

40.6.3.4. 동안

[ <<라벨 ]
동안부울 표현식토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

동안문은 다음과 같은 경우 일련의 문을 반복합니다.부울 표현식참으로 평가됩니다. 토토 꽁 머니 본문에 대한 각 항목 직전에 표현식이 검사됩니다.

예:

채무 금액  0 AND 선물_증명서 잔액  0 LOOP인 동안
    -- 여기에 몇 가지 계산이 있습니다.
엔드 토토 꽁 머니;

토토 꽁 머니가 완료되지 않은 동안
    -- 여기에 몇 가지 계산이 있습니다.
끝 토토 꽁 머니;

40.6.3.5. for(정수 변형)

[ <<라벨 ]
에 대한이름IN [반전] 표현 .. 표현 [BY표현 ] 토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

이 형태는for정수 값 범위를 반복하는 토토 꽁 머니를 생성합니다. 변수이름자동으로 유형으로 정의됩니다.정수그리고 토토 꽁 머니 내부에만 존재합니다(변수 이름의 기존 정의는 토토 꽁 머니 내에서 무시됩니다). 범위의 하한과 상한을 제공하는 두 표현식은 토토 꽁 머니에 들어갈 때 한 번 평가됩니다. 만약BY절이 지정되지 않았습니다. 반복 단계는 1입니다. 그렇지 않으면에 지정된 값입니다.BY절, 토토 꽁 머니 진입 시 다시 한 번 평가됩니다. 만일반전이 지정되면 각 반복 후에 단계 값이 더해지는 것이 아니라 빼집니다.

정수의 몇 가지 예for토토 꽁 머니:

i IN 1..10 토토 꽁 머니용
    -- 토토 꽁 머니 내에서 1,2,3,4,5,6,7,8,9,10 값을 사용하겠습니다.
엔드 토토 꽁 머니;

역방향 10..1 토토 꽁 머니의 i용
    -- 토토 꽁 머니 내에서 10,9,8,7,6,5,4,3,2,1 값을 사용하겠습니다.
엔드 토토 꽁 머니;

i에 대한 역방향 10..1 BY 2 토토 꽁 머니
    -- 토토 꽁 머니 내에서 10,8,6,4,2 값을 사용하겠습니다.
끝 토토 꽁 머니;

하한이 상한보다 큰 경우(또는 다음보다 작으면반전case), 토토 꽁 머니 본문이 전혀 실행되지 않습니다. 오류가 발생하지 않습니다.

만약에라벨다음에 첨부되어 있습니다.forloop 그러면 정수 토토 꽁 머니 변수는 이를 사용하여 정규화된 이름으로 참조될 수 있습니다.라벨.

40.6.4. 쿼리 결과 반복

다른 유형의 사용for토토 꽁 머니를 사용하면 쿼리 결과를 반복하고 이에 따라 해당 데이터를 조작할 수 있습니다. 구문은 다음과 같습니다.

[ <<라벨 ]
에 대한대상IN질의토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

대상는 레코드 변수, 행 변수 또는 쉼표로 구분된 스칼라 변수 목록입니다.대상다음의 결과로 각 행이 연속적으로 할당됩니다.질의그리고 토토 꽁 머니 본문은 각 행에 대해 실행됩니다. 예는 다음과 같습니다.

CREATE FUNCTION Refresh_mviews() 정수를 $$로 반환합니다.  
선언
    mviews 기록;
시작
    RAISE NOTICE '모든 구체화된 뷰를 새로 고치는 중...';
    동영상 조회수 IN
       SELECT n.nspname AS mv_schema,
              c.relname AS mv_name,
              pg_catalog.pg_get_userbyid(c.relowner) AS 소유자
         pg_catalog.pg_class c에서
    왼쪽 조인 pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
        여기서 c.relkind = 'm'
     1개로 주문하세요
    토토 꽁 머니

        -- 이제 "mviews"에는 구체화된 뷰에 대한 정보가 포함된 하나의 레코드가 있습니다.

        RAISE NOTICE '구체화된 뷰 %.%(소유자: %) 새로 고치는 중...',
                     quote_ident(mviews.mv_schema),
                     quote_ident(mviews.mv_name),
                     quote_ident(mviews.owner);
        '구체화된 뷰 새로 고침' 실행 || quote_ident(mviews.mv_schema)
                      || '.' || quote_ident(mviews.mv_name);
    엔드 토토 꽁 머니;

    RAISE NOTICE '구체화된 뷰 새로 고침이 완료되었습니다.';
    1을 반환합니다.
끝;
$$ 언어 plpgsql;

토토 꽁 머니가 다음에 의해 종료되는 경우종료문, 마지막으로 할당된 행 값은 토토 꽁 머니 후에도 계속 액세스할 수 있습니다.

질의이러한 유형에 사용됨for문은 호출자에게 행을 반환하는 모든 SQL 명령이 될 수 있습니다.선택가장 일반적인 경우이지만 다음을 사용할 수도 있습니다.삽입, 업데이트또는삭제돌아오는 중절. 다음과 같은 일부 유틸리티 명령설명역시 작동합니다.

PL/pgSQL변수는 쿼리 텍스트로 대체되고 쿼리 계획은 재사용이 가능하도록 캐시됩니다. 자세한 내용은 다음에 설명되어 있습니다.섹션 40.10.1그리고섹션 40.10.2.

실행 중문은 행을 반복하는 또 다른 방법입니다.

[ <<라벨 ]
에 대한대상실행 중텍스트 표현 [사용 중표현 [, ... ] ] 토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

이것은 소스 쿼리가 문자열 표현식으로 지정된다는 점을 제외하면 이전 양식과 유사하며, 이는 각 항목에 대해 평가되고 다시 계획됩니다.for토토 꽁 머니. 이를 통해 프로그래머는 일반 쿼리와 마찬가지로 미리 계획된 쿼리의 속도나 동적 쿼리의 유연성을 선택할 수 있습니다.실행문장. 마찬가지로실행, 매개변수 값은 다음을 통해 동적 명령에 삽입될 수 있습니다.사용 중.

결과가 반복되어야 하는 쿼리를 지정하는 또 다른 방법은 커서로 선언하는 것입니다. 이에 대한 설명은섹션 40.7.4.

40.6.5. 배열을 통한 반복

FOREACH토토 꽁 머니는 a와 매우 유사합니다.for토토 꽁 머니이지만 SQL 쿼리에서 반환된 행을 반복하는 대신 배열 값의 요소를 반복합니다. (일반적으로,FOREACH은 복합 값 표현식의 구성 요소를 반복하는 데 사용됩니다. 배열 외에 합성물을 통한 반복을 위한 변형은 향후 추가될 수 있습니다.)FOREACH배열을 반복하는 명령문은 다음과 같습니다:

[ <<라벨 ]
FOREACH대상 [슬라이스번호 ] 배열표현토토 꽁 머니문장END 토토 꽁 머니 [ 라벨 ];

없이슬라이스또는 만약슬라이스 0이 지정되면 토토 꽁 머니는 다음을 평가하여 생성된 배열의 개별 요소를 반복합니다.표현.대상변수에는 각 요소의 값이 순차적으로 할당되고 각 요소에 대해 토토 꽁 머니 본문이 실행됩니다. 다음은 정수 배열의 요소를 반복하는 예입니다.

CREATE FUNCTION sum(int[])는 int8을 $$로 반환합니다.
선언
  s int8 := 0;
  x 정수;
시작
  FOREACH x IN 배열 $1
  토토 꽁 머니
    s := s + x;
  엔드 토토 꽁 머니;
  반환;
끝;
$$ 언어 plpgsql;

배열 차원 수에 관계없이 저장 순서대로 요소를 방문합니다. 비록대상는 일반적으로 단일 변수일 뿐이며, 복합 값(레코드) 배열을 반복할 때 변수 목록이 될 수 있습니다. 이 경우 각 배열 요소에 대해 변수는 복합 값의 연속 열에서 할당됩니다.

긍정적으로슬라이스값,FOREACH단일 요소가 아닌 배열의 조각을 반복합니다.슬라이스값은 배열의 차원 수보다 크지 않은 정수 상수여야 합니다.대상변수는 배열이어야 하며 배열 값의 연속적인 조각을 수신합니다. 여기서 각 조각은 다음에 의해 지정된 차원 수에 속합니다.슬라이스. 다음은 1차원 슬라이스를 반복하는 예입니다.

함수 생성 scan_rows(int[]) $$로 void 반환
선언
  x 정수[];
시작
  배열 $1의 FOREACH x 슬라이스 1
  토토 꽁 머니
    알림 발생 '행 = %', x;
  엔드 토토 꽁 머니;
끝;
$$ 언어 plpgsql;

SELECT scan_rows(ARRAY[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]);

주의사항: 행 = 1,2,3

40.6.6. 트래핑 오류

기본적으로 a에서 발생하는 모든 오류는PL/pgSQL함수는 함수 실행을 중단하고 실제로 주변 트랜잭션도 중단합니다. 다음을 사용하여 오류를 포착하고 복구할 수 있습니다.시작다음으로 차단예외절. 구문은 a에 대한 일반 구문의 확장입니다.시작차단:

[ <<라벨 ]
[선언선언 ]
시작문장예외
    언제조건 [또는조건 ... ] 그럼handler_statements
    [언제조건 [또는조건 ... ] 그러면handler_statements
      ... ]
끝;

오류가 발생하지 않으면 이 블록 형태는 단순히 모든 것을 실행합니다.문장, 그 후 제어는 다음 명령문으로 전달됩니다.END. 그러나 내에서 오류가 발생하면문장, 다음 처리 중문장이(가) 버려지고 토토 꽁 머니권이로 넘어갑니다.예외목록. 목록이 처음으로 검색됩니다.조건발생한 오류와 일치합니다. 일치하는 항목이 발견되면 해당handler_statements실행된 후 제어는 다음 명령문으로 넘어갑니다.END. 일치하는 항목이 없으면 오류는 다음과 같이 전파됩니다.예외절이 전혀 없었습니다. 오류는 다음을 포함하는 블록에 의해 포착될 수 있습니다.예외, 또는 아무것도 없으면 함수 처리를 중단합니다.

조건이름은 다음에 표시된 이름 중 하나일 수 있습니다.범퍼카 토토 : 문서 : 9.4 : 범퍼카 토토 범퍼카 토토 코드. 카테고리 이름은 해당 카테고리 내의 모든 오류와 일치합니다. 특수 조건 이름기타다음을 제외한 모든 오류 유형과 일치QUERY_CANCELED. (덫을 놓는 것이 가능하지만 종종 현명하지 못한 경우가 많습니다.QUERY_CANCELED이름별.) 조건 이름은 대소문자를 구분하지 않습니다. 또한 오류 조건은 다음과 같이 지정할 수 있습니다.SQLSTATE코드; 예를 들어 다음은 동일합니다.

division_by_zero 다음에는 ...
SQLSTATE '22012' 다음 ...

선택한 항목 내에서 새로운 오류가 발생하는 경우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, 그러나 그 효과는업데이트명령이 롤백됩니다.삽입블록 앞의 명령은 롤백되지 않으므로 최종 결과는 데이터베이스에톰 존스아님조 존스.

팁:다음을 포함하는 블록예외절은 없는 블록보다 들어가고 나가는 데 비용이 훨씬 더 많이 듭니다. 그러므로 사용하지 마십시오.예외필요 없이.

예 40-2. 의 예외업데이트/삽입

이 예에서는 다음 중 하나를 수행하기 위해 예외 처리를 사용합니다.업데이트또는삽입, 적절하게:

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, '데니스');

이 코딩은 다음을 가정합니다.unique_violation오류는 다음에 의해 발생합니다.삽입, 말하자면, 가 아니라삽입테이블의 트리거 기능에서. 오류를 일으킨 인덱스에 관계없이 작업을 재시도하므로 테이블에 고유 인덱스가 두 개 이상 있는 경우에도 오작동할 수 있습니다. 트랩된 오류가 예상한 오류인지 확인하기 위해 다음에 설명된 기능을 사용하면 더 많은 안전성을 확보할 수 있습니다.

40.6.6.1. 오류에 대한 정보 얻기

예외 핸들러는 발생한 특정 오류를 식별해야 하는 경우가 많습니다. 현재 예외에 대한 정보를 얻는 방법에는 두 가지가 있습니다.PL/pgSQL: 특수 변수 및스택 진단 받기명령.

예외 핸들러 내에서 특수 변수SQLSTATE발생한 예외에 해당하는 오류 코드를 포함합니다(참조표 A-1가능한 오류 코드 목록 참조). 특수 변수SQLERRM예외와 관련된 오류 메시지가 포함되어 있습니다. 이러한 변수는 예외 처리기 외부에서 정의되지 않습니다.

예외 처리기 내에서 다음을 사용하여 현재 예외에 대한 정보를 검색할 수도 있습니다.스택 진단 받기다음 형식의 명령:

스택 진단 받기변수 { = | := } 항목 [ , ... ];

각각항목지정된 항목에 할당될 상태 값을 식별하는 키워드입니다.변수(수신하려면 올바른 데이터 유형이어야 함). 현재 사용 가능한 상태 항목은 다음과 같습니다.표 40-2.

표 40-2. 오류 진단 항목

이름 유형 설명
RETURNED_SQLSTATE 텍스트 예외의 SQLSTATE 오류 코드
COLUMN_NAME 텍스트 예외 관련 컬럼 이름
CONSTRAINT_NAME 텍스트 예외 관련 제약 조건의 이름
PG_DATATYPE_NAME 텍스트 예외 관련 데이터 유형의 이름
MESSAGE_TEXT 텍스트 예외의 기본 메시지 텍스트
TABLE_NAME 텍스트 예외 관련 테이블 이름
SCHEMA_NAME 텍스트 예외 관련 스키마 이름
PG_EXCEPTION_DETAIL 텍스트 예외 세부 메시지 텍스트(있는 경우)
PG_EXCEPTION_HINT 텍스트 예외 힌트 메시지 텍스트(있는 경우)
PG_EXCEPTION_CONTEXT 텍스트 예외 발생 시 호출 스택을 설명하는 텍스트 줄(참조섹션 40.6.7)

예외가 항목에 대한 값을 설정하지 않은 경우 빈 문자열이 반환됩니다.

다음은 예입니다:

선언하다
  text_var1 텍스트;
  text_var2 텍스트;
  text_var3 텍스트;
시작
  -- 예외가 발생할 수 있는 일부 처리
  ...
그 외의 경우에는 예외
  스택 진단 받기 text_var1 = MESSAGE_TEXT,
                          text_var2 = PG_EXCEPTION_DETAIL,
                          text_var3 = PG_EXCEPTION_HINT;
끝;

40.6.7. 실행 위치 정보 획득

진단 받기명령, 이전에 설명됨섹션 40.5.5, 현재 실행 상태에 대한 정보를 검색합니다(반면스택 진단 받기53291_53393PG_CONTEXT상태 항목은 현재 실행 위치를 식별하는 데 유용합니다.PG_CONTEXT호출 스택을 설명하는 텍스트 줄이 포함된 텍스트 문자열을 반환합니다. 첫 번째 줄은 현재 함수와 현재 실행 중인 함수를 나타냅니다.진단 받기명령. 두 번째 및 후속 줄은 호출 스택의 상위에 있는 함수 호출을 참조합니다. 예를 들면:

함수 생성 또는 교체 external_func() 정수를 $$로 반환합니다.
시작
  RETURN inner_func();
끝;
$$ 언어 plpgsql;

함수 생성 또는 교체 inner_func()는 정수를 $$로 반환합니다.
선언
  스택 텍스트;
시작
  진단 받기 스택 = PG_CONTEXT;
  RAISE NOTICE E'--- 콜 스택 ---\n%', stack;
  1을 반환합니다.
끝;
$$ 언어 plpgsql;

SELECT 외부_기능();

주의 사항: --- 호출 스택 ---
GET DIAGNOSTICS의 PL/pgSQL 함수 inner_func() 라인 5
RETURN의 PL/pgSQL 함수 external_func() 라인 3
CONTEXT: RETURN의 PL/pgSQL 함수 external_func() 라인 3
 외부_기능
 ------------
           1
(1행)

스택 진단 받기 ... PG_EXCEPTION_CONTEXT동일한 종류의 스택 추적을 반환하지만 현재 위치가 아닌 오류가 감지된 위치를 설명합니다.