41.7. 토토 캔#

한 번에 전체 쿼리를 실행하는 대신 A를 설정할 수 있습니다.토토 캔쿼리를 캡슐화 한 다음 쿼리 결과를 한 번에 몇 행에 읽습니다. 이를 수행하는 한 가지 이유는 결과에 많은 행이 포함되어있을 때 메모리 오버런을 피하기 때문입니다. (하지만,pl/pgsql사용자는 일반적으로 그것에 대해 걱정할 필요가 없습니다.for루프는 메모리 문제를 피하기 위해 내부적으로 토토 캔를 자동으로 사용합니다.) 더 흥미로운 사용법은 함수가 만든 토토 캔에 대한 참조를 반환하여 발신자가 행을 읽을 수 있도록하는 것입니다. 이것은 기능에서 큰 행 세트를 반환하는 효율적인 방법을 제공합니다.

41.7.1. 토토 캔 변수 선언#

토토 캔에 대한 모든 액세스pl/pgsql항상 특수 데이터 유형의 토토 캔 변수를 통과합니다Refcursor. 토토 캔 변수를 생성하는 한 가지 방법은 유형 변수로 선언하는 것입니다Refcursor. 또 다른 방법은 토토 캔 선언 구문을 사용하는 것입니다. 일반적으로 :

이름[[아니오] 스크롤] 토토 캔 [(인수)] forQuery;

(for로 대체 할 수 있습니다isforOracle호환성.) if스크롤지정되어 있으면 토토 캔는 뒤로 스크롤 할 수 있습니다. 만약에스크롤 없음지정되어 있으면 뒤로 페치가 거부됩니다. 사양이 나타나지 않으면 뒤로 페치가 허용되는지 여부는 쿼리 의존적입니다.인수지정된 경우 쉼표로 구분 된 쌍의 목록입니다.이름 DataType주어진 쿼리의 매개 변수 값으로 대체 할 이름을 정의하는 것. 이 이름을 대체 할 실제 값은 토토 캔가 열리면 나중에 지정됩니다.

일부 예 :

선언
    CURS1 Refcursor;
    select * from tenk1에 대한 curs2 cursor;
    select * from tenk1에 대한 curs3 cursor (키 정수).

이 세 가지 변수 모두 데이터 유형이 있습니다Refcursor그러나 첫 번째는 쿼리와 함께 사용할 수 있지만 두 번째는 완전히 지정된 쿼리가 있습니다bound그것에, 그리고 마지막에는 매개 변수화 된 쿼리가 있습니다. (토토 캔가 열리면 정수 매개 변수 값으로 대체됩니다.) 변수CURS1Unbound특정 쿼리에 바인딩되지 않기 때문에

the스크롤토토 캔의 쿼리가 사용될 때 옵션을 사용할 수 없습니다업데이트/공유. 또한 사용하는 것이 가장 좋습니다스크롤 없음휘발성 함수와 관련된 쿼리가 포함되어 있습니다. 의 구현스크롤쿼리의 출력을 다시 읽으면 휘발성 기능이 수행하지 않을 수있는 일관된 결과가 제공 될 것이라고 가정합니다.

41.7.2. 토토 캔 열기#

토토 캔를 사용하기 전에 행을 검색하기 전에오픈. (이것은 SQL 명령과 동등한 조치입니다토토 캔 선언.)pl/pgsql세 가지 형태의Open명령문, 두 개의 문자는 언 바운드 토토 캔 변수를 사용하고 세 번째는 바운드 토토 캔 변수를 사용합니다.

Note

바운드 토토 캔 변수는 토토 캔를 명시 적으로 열지 않고도 사용할 수 있습니다.for설명섹션 41.7.4. 에이for루프가 토토 캔를 열고 루프가 완료되면 다시 닫습니다.

토토 캔를 열면 A라는 서버 내부 데이터 구조를 작성해야합니다.포털, 토토 캔 쿼리의 실행 상태를 보유합니다. 포털에는 이름이 있으며, 이는 포털 존재 기간 동안 세션 내에서 독특해야합니다. 기본적으로pl/pgsql생성하는 각 포털에 고유 한 이름을 할당합니다. 그러나 널이 아닌 문자열 값을 토토 캔 변수에 할당하면 해당 문자열이 포털 이름으로 사용됩니다. 이 기능은에 설명 된대로 사용할 수 있습니다.섹션 41.7.3.5.

41.7.2.1. Open for 쿼리 #

Openunbound_cursorvar[[아니오] 스크롤] for쿼리;

토토 캔 변수가 열리고 지정된 쿼리가 제공됩니다. 토토 캔는 이미 열 수 없으며, 결합되지 않은 토토 캔 변수로 선언되었을 것입니다 (즉, 간단하게Refcursor변수). 쿼리는 여야합니다.select또는 행을 반환하는 다른 것 (예 :설명). 쿼리는 다른 SQL 명령과 같은 방식으로 처리됩니다.pl/pgsql: pl/pgsql가변 이름이 대체되고 쿼리 계획이 재사용 될 수 있도록 캐시됩니다. Apl/pgsql변수가 토토 캔 쿼리로 대체되며, 대체 된 값은의 값입니다.Open; 변수에 대한 후속 변경은 토토 캔의 동작에 영향을 미치지 않습니다. 그만큼스크롤and스크롤 없음옵션은 바운드 토토 캔와 같은 의미를 갖습니다.

예 :

select * from foo where key = mykey;의 curs1을 엽니 다.

41.7.2.2. execute를 위해 열기 #

Openunbound_cursorvar[[아니오] 스크롤] executequery_string[사용표현[, ... ]];

토토 캔 변수가 열리고 지정된 쿼리가 제공됩니다. 토토 캔는 이미 열 수 없으며, 결합되지 않은 토토 캔 변수로 선언되었을 것입니다 (즉, 간단하게Refcursor변수). 쿼리는와 같은 방식으로 문자열 표현식으로 지정됩니다.execute명령. 평소와 같이, 이것은 유연성을 제공하므로 쿼리 계획은 한 번에서 다음 실행마다 다를 수 있습니다 (참조섹션 41.11.2), 또한 명령 문자열에서 변수 대체가 수행되지 않았 음을 의미합니다. 와 마찬가지로execute, 매개 변수 값을 동적 명령에 삽입 할 수 있습니다format ()and사용. 그만큼스크롤and스크롤 없음옵션은 바운드 토토 캔와 동일한 의미를 갖습니다.

예 :

Execute Format의 CURS1 열기 ( 'select * from %i where col1 = $ 1', tabname) keyValue;

이 예에서 테이블 이름은 쿼리에 삽입됩니다format (). 에 대한 비교 값col1A를 통해 삽입됩니다사용매개 변수이므로 인용이 필요하지 않습니다.

41.7.2.3. 바운드 토토 캔 열기#

Openbound_cursorvar[([ argument_name: =]argument_value[, ...])];

이 형태의Open쿼리가 선언 될 때 쿼리가 묶인 토토 캔 변수를 열는 데 사용됩니다. 토토 캔는 이미 열 수 없습니다. 토토 캔가 인수를 받으라고 선언 된 경우에만 실제 인수 값 표현 목록이 나타나야합니다. 이 값은 쿼리에서 대체됩니다.

바운드 토토 캔에 대한 쿼리 계획은 항상 캐시 가능한 것으로 간주됩니다. 에 해당하지 않습니다.execute이 경우. 주석스크롤and스크롤 없음에서 지정할 수 없습니다Open, 토토 캔의 스크롤 행동이 이미 결정되었으므로

인수 값은 하나를 사용하여 전달 될 수 있습니다위치또는이름표기법. 위치 표기법에서는 모든 인수가 순서대로 지정됩니다. 명명 된 표기법에서 각 인수의 이름은를 사용하여 지정됩니다.: =그것을 인수 표현에서 분리하려면. 에 설명 된 함수 호출과 유사합니다범퍼카 토토 캔 : 문서 : 17 : 4.3. 함수 호출, 위치와 이름이 지정된 표기법을 혼합 할 수 있습니다.

예제 (위의 토토 캔 선언 예제를 사용) :

Open CURS2;
열린 curs3 (42);
CURS3 열기 (키 : = 42);

가변 대체는 바운드 토토 캔의 쿼리에서 수행되므로 토토 캔에 값을 전달하는 두 가지 방법이 있습니다.Openpl/pgsql쿼리의 변수. 그러나 바운드 토토 캔가 선언되기 전에 선언 된 변수만이 대체 될 것입니다. 두 경우 모두 통과 할 값은 당시 결정됩니다.Open. 예를 들어, 또 다른 방법은와 같은 효과를 얻는다.CURS3위의 예는

선언
    키 정수;
    select * from tenk1에 대한 curs4 cursor where ightorian1 = key;
시작하다
    키 : = 42;
    오픈 커스 4;

41.7.3. 토토 캔 사용#

토토 캔가 열리면 여기에 설명 된 진술로 조작 할 수 있습니다.

이러한 조작은 토토 캔를 열었던 동일한 함수에서 발생할 필요가 없습니다. 당신은 a를 반환 할 수 있습니다.Refcursor함수에서 값을 벗어나 발신자가 토토 캔에서 작동하도록합니다. (내부적으로 ARefcursor값은 단순히 토토 캔의 활성 쿼리를 포함하는 포털의 문자열 이름입니다. 이 이름은 주변을 지나갈 수 있으며 다른 사람에게 할당Refcursor포털을 방해하지 않고 변수 등.)

모든 포털은 트랜잭션 종료시 암시 적으로 닫힙니다. 따라서 aRefcursor값은 거래가 끝날 때까지 열린 토토 캔를 참조하는 데 사용할 수 있습니다.

41.7.3.1. fetch #

fetch [ 방향From | 안에]토토 캔in대상;

fetch다음 행 (표시된 방향으로)을 토토 캔에서 대상으로 검색합니다.이 행 변수, 레코드 변수 또는 쉼표로 구분 된 간단한 변수 목록이 될 수 있습니다.. 적절한 행이 없으면 대상이 NULL로 설정됩니다. 와 마찬가지로선택, 특별 변수발견행이 획득되었는지 여부를 확인할 수 있습니다. 행을 얻지 못하면 토토 캔는 이동 방향에 따라 마지막 행 후 또는 첫 번째 행 앞에 위치합니다.

the방향조항은 SQL에서 허용되는 변형 중 하나 일 수 있습니다fetch하나 이상의 행을 가져올 수있는 명령을 제외하고; 즉,다음, Prior, 첫 번째, 마지막, 절대 count, 상대 count, Forward또는뒤로. 생략방향지정과 동일합니다다음. a를 사용하여 형식으로count, ThecountSQL과 달리 정수 값 표현이 될 수 있습니다.fetch명령, 정수 만 상수 만 허용).방향뒤로 이동 해야하는 값은 토토 캔가 선언되거나 열리지 않으면스크롤옵션.

토토 캔A의 이름이어야합니다Refcursor열린 토토 캔 포털을 참조하는 변수.

예 :

curs1을 Rowvar로 가져옵니다.
curs2를 foo, bar, baz로 가져옵니다.
Curs3에서 x, y로 마지막으로 가져 오십시오.
CURS4에서 X 로의 상대적 -2를 가져옵니다.

41.7.3.2. 움직임 #

이동 [ 방향From | 안에]토토 캔;

움직임데이터를 검색하지 않고 토토 캔를 재배치합니다.움직임Fetch명령. 그만큼방향조항은 SQL에서 허용되는 변형 중 하나 일 수 있습니다fetch명령, 하나 이상의 행을 가져올 수있는 명령; 토토 캔는 마지막 행에 위치합니다. (그러나방향절은 단순히 A입니다.count키 단어가없는 표현식에서pl/pgsql. 그 구문은의 경우에 모호합니다.방향조항은 완전히 생략되므로이면 실패 할 수 있습니다.count상수는 아닙니다.)와 마찬가지로선택, 특별 변수발견로 이동할 행이 있는지 확인할 수 있습니다. 그러한 행이없는 경우, 토토 캔는 이동 방향에 따라 마지막 행 뒤에 또는 첫 번째 행 앞에 위치합니다.

예 :

CURS1 움직임;
CURS3에서 마지막으로 이동;
CURS4에서 상대적 -2를 이동;
Curs4에서 2를 앞으로 이동;

41.7.3.3. 현재의 현재 위치 업데이트/삭제 #

업데이트테이블SET ... 현재의 전류토토 캔;테이블현재의 위치토토 캔;

토토 캔가 테이블 행에 배치되면 해당 행을 토토 캔를 사용하여 행을 업데이트하거나 삭제하여 행을 식별 할 수 있습니다. 토토 캔의 쿼리가 무엇인지 (특히 그룹화 없음)에 대한 제한이 있으며 사용하는 것이 가장 좋습니다업데이트토토 캔에서. 자세한 내용은를 참조하십시오.선언참조 페이지.

예 :

업데이트 foo set dataval = myval where curs1;

41.7.3.4. 닫기 #

닫기토토 캔;

닫기열린 토토 캔의 기본 포털을 닫습니다. 이것은 트랜잭션 종료 전에 일찍 리소스를 릴리스하거나 토토 캔 변수를 다시 열 수있는 데 사용될 수 있습니다.

예 :

Close Curs1;

41.7.3.5. 반환 토토 캔#

pl/pgsql함수는 토토 캔를 발신자에게 반환 할 수 있습니다. 이것은 여러 행이나 열, 특히 매우 큰 결과 세트에서 반환하는 데 유용합니다. 이를 위해 함수는 토토 캔를 열고 토토 캔 이름을 발신자에게 반환합니다 (또는 발신자에게 지정된 또는 다른 것으로 알려진 포털 이름을 사용하여 토토 캔를 엽니 다). 그런 다음 발신자는 토토 캔에서 행을 가져올 수 있습니다. 발신자가 토토 캔를 닫을 수 있거나 트랜잭션이 닫히면 자동으로 닫힙니다.

토토 캔에 사용되는 포털 이름은 프로그래머가 지정하거나 자동으로 생성 될 수 있습니다. 포털 이름을 지정하려면에 문자열을 할당합니다.Refcursor열기 전에 변수. 의 문자열 값Refcursor변수는 사용합니다.Open기본 포털의 이름으로. 그러나이면RefcursorVariable의 값은 null입니다 (기본적으로).Open기존 포털과 충돌하지 않는 이름을 자동으로 생성하고에 할당합니다.Refcursor변수.

Note

이전PostgreSQL16, 바운드 토토 캔 변수는 널로 남겨 두지 않고 자체 이름을 포함하도록 초기화되었으므로 기본 포털 이름은 기본적으로 토토 캔 변수 이름과 동일합니다. 이것은 다른 기능에서 비슷한 이름의 토토 캔 사이에 충돌 위험이 너무 많아서 변경되었습니다.

다음 예제는 발신자가 토토 캔 이름을 제공 할 수있는 한 가지 방법을 보여줍니다.

테이블 테스트 생성 (col 텍스트);
테스트 값에 삽입 ( '123');

기능 reffunc (refcursor) 생성 refcursor를 다시 반환합니다.
시작하다
    Test에서 COL SELECT COL에 대해 $ 1을 엽니 다;
    $ 1의 반환;
끝;
'언어 plpgsql;

시작하다;
Reffunc ( 'funccursor')을 선택하십시오.
funccursor에서 모두 가져 오십시오.
저지르다;

다음 예제는 자동 토토 캔 이름 생성을 사용합니다 :

함수 만들기 reffunc2 () refcursor를 반환합니다.
선언하다
    refcursor;
시작하다
    테스트에서 COL SELECT COL에 대한 공개 심판;
    반환 심판;
끝;
'언어 plpgsql;

- 토토 캔를 사용하려면 거래에 있어야합니다.
시작하다;
선택 reffunc2 ();

      Reffunc2
-------------------
 <이름이없는 토토 캔 1
(1 줄)

"<이름없는 토토 캔 1"에서 모두 가져 오십시오.
저지르다;

다음 예제는 단일 함수에서 여러 토토 캔를 반환하는 한 가지 방법을 보여줍니다.

함수 생성 myfunc (refcursor, refcursor)는 refcursor를 $$로 반환합니다
시작하다
    table_1에서 선택 *에 대해 $ 1을 엽니 다;
    다음 $ 1;
    table_2에서 select *에 대해 $ 2를 엽니 다;
    다음 $ 2를 반환합니다.
끝;
$$ 언어 plpgsql;

- 토토 캔를 사용하려면 거래에 있어야합니다.
시작하다;

myfunc ( 'a', 'b')에서 *를 선택하십시오.

a에서 모두 가져 오십시오.
b에서 모두 가져 오십시오.
저지르다;

41.7.4. 토토 캔의 결과를 통한 반복#

의 변형이 있습니다for토토 캔가 반환 한 행을 반복 할 수있는 명령문. 구문은 다음과 같습니다.

[ <<레이블 ]
을 위한RecordVarinbound_cursorvar[([ argument_name: =]argument_value[, ...])] loop진술엔드 루프 [ 레이블 ];

토토 캔 변수가 선언 될 때 일부 쿼리에 바인딩되었을 것입니다.할 수 없음이미 열려 있습니다. 그만큼for명령문은 자동으로 토토 캔를 열고 루프가 종료되면 토토 캔를 다시 닫습니다. 토토 캔가 인수를 받으라고 선언 된 경우에만 실제 인수 값 표현 목록이 나타나야합니다. 이 값은 쿼리에서 |Open(참조섹션 41.7.2.3).

변수RecordVar자동으로 유형으로 정의레코드루프 내부에만 존재합니다 (변수 이름의 기존 정의는 루프 내에서 무시됩니다). 토토 캔가 반환 한 각 행은이 레코드 변수에 연속적으로 할당되며 루프 본체가 실행됩니다.

수정 제출

문서에 올바른 것이 없으면 일치하지 않습니다. 특정 기능에 대한 귀하의 경험 또는 추가 설명이 필요합니다. 사용이 양식문서 문제를보고하려면