with
사설 토토 (공통 테이블 표현)with
더 큰 사설 토토에서 사용하기 위해 보조 문을 작성하는 방법을 제공합니다. 이 진술은 종종 일반적인 테이블 표현 또는이라고합니다.CTEs는 하나의 사설 토토에만 존재하는 임시 테이블을 정의하는 것으로 생각할 수 있습니다. a의 각 보조 문장with
조항이 될 수 있습니다select
, 삽입
, 업데이트
또는삭제
; 그리고with
절 자체는 A 일 수있는 기본 설명에 첨부됩니다.select
, 삽입
, 업데이트
또는삭제
.
select
inwith
기본 값select
inwith
복잡한 사설 토토를 더 간단한 부품으로 분해하는 것입니다. 예는 다음과 같습니다.
greal_sales as ( Total_sales로 영역, 합 (금액)을 선택하십시오 주문에서 지역별 그룹 ), top_regions as ( 지역을 선택하십시오 regional_sales에서 여기서 total_sales (select sum (total_sales)/regional_sales에서 10) )) 지역 선택, 제품, sum (수량)으로 product_units, sum (금액)은 product_sales입니다 주문에서 지역 (Top_regions에서 지역 선택) 지역별 그룹, 제품;
상위 판매 지역에서만 제품 별 판매량을 표시합니다. 그만큼with
조항은 두 개의 보조 문서를 정의합니다.Regional_sales
andTOP_REGIONS
Regional_sales
TOP_REGIONS
의 출력TOP_REGIONS
기본에서 사용됩니다select
사설 토토. 이 예는없이 쓰여졌을 수 있습니다.with
, 그러나 우리는 두 가지 레벨의 중첩 하위가 필요했을 것입니다select
s. 이런 식으로 따르는 것이 조금 더 쉽습니다.
선택 사항재귀
수정 자 변경with
단순한 구문 편의에서 표준 SQL에서 불가능한 것을 달성하는 기능으로. 사용재귀
, awith
사설 토토는 자체 출력을 참조 할 수 있습니다. 매우 간단한 예는 1 ~ 100의 정수를 합산하는이 사설 토토입니다.
재귀 t (n) as ( 값 (1) 모두 n <100에서 n+1을 선택하십시오 )) t;에서 합 (n)을 선택하십시오.
재귀의 일반적인 형태with
사설 토토는 항상입니다.비 수거 용어,Union
(또는Union All
), a재귀 용어, 여기서 재귀 용어 만 쿼리의 자체 출력에 대한 참조를 포함 할 수 있습니다. 이러한 쿼리는 다음과 같이 실행됩니다.
재귀 쿼리 평가
회수 기간을 평가합니다. 을 위한Union
(하지만Union All
), 중복 행을 버립니다. 재귀 쿼리 결과에 남은 모든 행을 포함시키고 임시로 배치하십시오작업대.
작업 테이블이 비어 있지 않은 한 다음 단계를 반복하십시오.
재귀 적 자기 참조를 위해 작업대의 현재 내용을 대체하여 재귀 용어를 평가합니다. 을 위한Union
(하지만Union All
), 이전 결과 행을 복제하는 중복 행과 행을 폐기하십시오. 재귀 쿼리 결과에 남은 모든 행을 포함시키고 임시로 배치하십시오중간 표.
작업대의 내용을 중간 테이블의 내용으로 교체 한 다음 중간 테이블을 비우십시오.
while재귀
쿼리를 재귀 적으로 지정할 수있게되며, 내부적으로 이러한 쿼리는 반복적으로 평가됩니다.
위의 예에서 작업 테이블은 각 단계에서 단일 행을 가지며 연속 단계에서 1 ~ 100의 값을 취합니다. 100 번째 단계에서는 때문에 출력이 없습니다.여기서
절, 따라서 사설 토토가 종료됩니다.
재귀 쿼리는 일반적으로 계층 또는 트리 구조화 된 데이터를 다루는 데 사용됩니다. 유용한 예는 즉각적인 포함을 보여주는 테이블 만 주어진 제품의 모든 직접적이고 간접적 인 하위 부분을 찾는이 쿼리입니다.
재귀 포함 포함 _parts (sub_part, part, rotity) as ( sub_part, part, part에서 part = 'our_product'를 선택하십시오. 모두 p.sub_part, p.part, p.quantity * pr.quantity를 선택하십시오 포함 _parts pr, parts p 여기서 p.part = pr.sub_part )) sub_part, sum (수량)을 total_quantity로 선택하십시오 conlude_parts에서 sub_part의 그룹
재귀 쿼리로 작업 할 때 쿼리의 재귀 부분이 결국 튜플을 반환하지 않으면 쿼리가 무기한으로 반복되는지 확인하는 것이 중요합니다. 때로는 사용Union
대신Union All
이전 출력 행을 복제하는 행을 폐기하여이를 달성 할 수 있습니다. 그러나 종종 사이클에는 완전히 복제 된 출력 행이 포함되지 않습니다. 이전에 동일한 지점에 도달했는지 확인하려면 하나 또는 몇 개의 필드 만 확인해야 할 수도 있습니다. 이러한 상황을 처리하는 표준 방법은 이미 방문한 값의 배열을 계산하는 것입니다. 예를 들어, 테이블을 검색하는 다음 쿼리를 고려하십시오그래프
a 사용링크
필드 :
recursive search_graph (id, link, data, depth) as ( G.ID, G.Link, G.Data, 1을 선택하십시오 그래프 g에서 모두 G.ID, G.Link, G.Data, Sg.Depth + 1을 선택하십시오 그래프 G, search_graph sg에서 여기서 g.id = sg.link )) sexect *에서 search_graph;
이 사설 토토는이면 루프됩니다.링크
관계에는주기가 포함됩니다. 우리가 필요하기 때문에“깊이”출력, 그냥 변경Union All
toUnion
루핑을 제거하지 않습니다. 대신 우리는 특정 링크 경로를 따르면서 같은 행에 다시 도달했는지 여부를 인식해야합니다. 두 개의 열을 추가합니다Path
and사이클
루프가 발생하기 쉬운 사설 토토 :
Recursive search_graph (id, 링크, 데이터, 깊이, 경로, 사이클) G.ID, G.Link, G.Data, 1, 1, 배열 [g.id], 거짓 그래프 g에서 모두 G.ID, G.Link, G.Data, Sg.Depth + 1, 경로 || g.id, g.id = 모든 (경로) 그래프 G, search_graph sg에서 여기서 g.id = sg.link 및 순환이 아닙니다 )) sexect *에서 search_graph;
사이클을 방지하는 것 외에도 배열 값은 종종 자체적으로 유용합니다.“Path”특정 행에 도달하기 위해 촬영.
주기를 인식하기 위해 둘 이상의 필드를 점검 해야하는 일반적인 경우 행을 사용하십시오. 예를 들어, 필드를 비교 해야하는 경우F1
andF2
:
recursive search_graph (id, 링크, 데이터, 깊이, 경로, 사이클) G.ID, G.Link, G.Data, 1, 1, 배열 [행 (G.F1, G.F2)], 거짓 그래프 g에서 모두 G.ID, G.Link, G.Data, Sg.Depth + 1, 경로 || 행 (G.F1, G.F2), 행 (G.F1, G.F2) = 모든 (경로) 그래프 G, search_graph sg에서 여기서 g.id = sg.link 및 순환이 아닙니다 )) sexect *에서 search_graph;
생략row ()
사이클을 인식하기 위해 하나의 필드 만 확인 해야하는 공동 사례의 구문. 이를 통해 복합 유형 배열이 아닌 간단한 배열을 사용할 수있어 효율성이 높아집니다.
재귀 쿼리 평가 알고리즘은 광선 검색 순서에서 출력을 생성합니다. 외부 쿼리를 만들어 심도 우선 검색 순서로 결과를 표시 할 수 있습니다주문 by
a“PATH”이런 식으로 구성된 열.
루프가 a에 있는지 확실하지 않은 경우 사설 토토 테스트에 유용한 트릭Limit
부모 사설 토토에서. 예를 들어,이 사설 토토는없이 영원히 루프합니다.Limit
:
재귀 t (n) as ( 선택 1 모두 t에서 n+1을 선택하십시오 )) t 한계 100에서 n을 선택하십시오;
이것은 작동하기 때문에PostgreSQL의 구현은 A의 많은 행만 평가합니다.with
쿼리는 실제로 상위 쿼리에 의해 가져옵니다. 다른 시스템이 다르게 작동 할 수 있으므로이 트릭을 생산에 사용하는 것은 권장되지 않습니다. 또한 외부 쿼리가 재귀 쿼리의 결과를 정렬하거나 다른 테이블에 결합하면 일반적으로 작동하지 않습니다.이 경우 외부 쿼리는 일반적으로 모든를 가져 오려고합니다.with
어쨌든 쿼리의 출력.
유용한 속성with
쿼리는 부모 쿼리 또는 형제 자매가 한 번 이상 참조하더라도 부모 쿼리의 실행 당 한 번만 평가된다는 것입니다.with
사설 토토. 따라서 여러 장소에서 필요한 비싼 계산은 A 내에 배치 할 수 있습니다.with
중복 작업을 피하기위한 사설 토토. 또 다른 가능한 응용 프로그램은 부작용과 함께 함수의 원치 않는 다중 평가를 방지하는 것입니다. 그러나이 코인의 다른 쪽은 Optimizer가 상위 사설 토토의 제한을 A로 푸시 할 수 없다는 것입니다.with
일반 하위 퀘스트보다 사설 토토. 그만큼with
사설 토토는 일반적으로 상위 사설 토토가 나중에 버릴 수있는 행을 억제하지 않고 서면으로 평가됩니다. (그러나 위에서 언급했듯이 사설 토토에 대한 참조가 제한된 수의 행만 요구하면 평가가 일찍 중지 될 수 있습니다.)
위의 예제 만 표시with
select
, 그러나 같은 방식으로 첨부 할 수 있습니다삽입
, 업데이트
또는삭제
. 각각의 경우에는 메인 명령에서 참조 할 수있는 임시 테이블을 효과적으로 제공합니다.
with
데이터 수정 문을 사용할 수 있습니다 (삽입
, 업데이트
또는삭제
) inwith
. 이를 통해 동일한 사설 토토에서 여러 다른 작업을 수행 할 수 있습니다. 예는 다음과 같습니다.
mized_rows as ( 제품에서 삭제하십시오 어디 "날짜" = '2010-10-01'및 "날짜"< '2010-11-01' 반환 * )) Products_Log에 삽입하십시오 maze_rows에서 *를 선택하십시오;
이 사설 토토는 효과적으로 행을 움직입니다제품
toProducts_Log
. 그만큼삭제
inwith
지정된 행을 삭제합니다제품
반환
절; 그리고 기본 쿼리는 출력을 읽고을 삽입합니다.Products_Log
.
위의 예의 미세점은입니다.with
절에 첨부되어삽입
, 서브가 아닙니다.select
내에서삽입
. 데이터 수정 진술은에만 허용되기 때문에 필요합니다.with
최상위 성명서에 첨부 된 조항. 그러나 정상with
가시성 규칙이 적용되므로를 참조 할 수 있습니다.with
sub-의 명령문 출력select
.
데이터 수정 문의with
보통반환
조항 (참조섹션 6.424107_24167반환
절,not데이터 수정 명령문의 대상 테이블은 나머지 사설 토토에서 참조 할 수있는 임시 테이블을 형성합니다. 데이터 수정 명세서에서with
부족반환
절은 임시 표를 형성하지 않으며 나머지 사설 토토에서는 참조 할 수 없습니다. 그럼에도 불구하고 그러한 진술은 실행됩니다. 적절하지 않은 예는 다음과 같습니다.
t as ( foo에서 삭제하십시오 )) 바에서 삭제;
이 예제는 테이블에서 모든 행을 제거합니다foo
andbar
. 클라이언트에보고 된 영향을받는 행의 수에는에서만 제거 된 행만 포함됩니다.bar
.
데이터 수정 진술의 재귀 적 자기 참조는 허용되지 않습니다. 경우에 따라 재귀의 출력을 참조 하여이 제한을 해결할 수 있습니다with
, 예 :
재귀 포함 _parts (sub_part, part) as ( sub_part, part = 'our_product'부분에서 부품을 선택하십시오. 모두 p.sub_part, p.part를 선택하십시오 포함 _parts pr, parts p 여기서 p.part = pr.sub_part )) 부품에서 삭제하십시오 PART (conture_Parts에서 부품을 선택);
이 쿼리는 제품의 모든 직접적이고 간접적 인 하위 부분을 제거합니다.
데이터 수정 문의with
는 1 차 쿼리가 출력의 모든 (또는 실제로)를 읽는지 여부와 독립적으로 한 번 정확하게 한 번 실행되며 항상 완료됩니다. 이것은 규칙과 다릅니다select
inwith
: 이전 섹션에서 언급 한 바와 같이 aselect
기본 사설 토토가 출력을 요구하는 한만 운반됩니다.
하위 진술의with
는 서로 동시에 그리고 기본 사설 토토와 함께 실행됩니다. 따라서 데이터 수정 문을 사용할 때with
, 지정된 업데이트가 실제로 발생하는 순서는 예측할 수 없습니다. 모든 진술은 동일하게 실행됩니다스냅 샷(참조PostgreSQL : 문서 : 10 : 13 장. 무지개 토토 제어), 따라서“참조”대상 테이블에 대한 서로의 영향. 이것은 실제 행 업데이트의 실제 순서의 예측 불가능 성의 영향을 완화하며반환
데이터는 다른 변화를 전달하는 유일한 방법입니다with
하위 진술 및 기본 사설 토토. 이것의 예는에서입니다.
t as ( 업데이트 제품 세트 가격 = 가격 * 1.05 반환 * )) 선택 *에서 제품에서;
외부select
|업데이트
t as ( 업데이트 제품 세트 가격 = 가격 * 1.05 반환 * )) 선택 *에서 t; 선택
외부select
업데이트 된 데이터를 반환합니다.
단일 문서에서 같은 행을 두 번 업데이트하려는 것은 지원되지 않습니다. 수정 중 하나만 발생하지만 어느 것을 쉽게 예측하는 것은 쉽지 않으며 때로는 불가능합니다. 이는 동일한 문서에서 이미 업데이트 된 행을 삭제하는데도 적용됩니다. 업데이트 만 수행됩니다. 따라서 일반적으로 단일 문서에서 단일 행을 두 번 수정하지 않아야합니다. 특히 글쓰기를 피하십시오with
메인 문 또는 형제 자매 하위 진술에 의해 변경된 동일한 행에 영향을 줄 수있는 하위 진술. 그러한 진술의 효과는 예측할 수 없습니다.
현재, 데이터 수정 명령문의 대상으로 사용 된 모든 테이블with
조건부 규칙도 없어야합니다.또한
규칙, 또는대신
여러 진술로 확장하는 규칙.