다른 프로그래밍 언어에서 SQL로 돌아 오면 재귀 쿼리의 구조는 다소 이상하게 보입니다. 단계별로 살펴보면 부서지는 것처럼 보입니다.
다음과 같은 간단한 예를 고려하십시오.
CREATE TABLE #NUMS
(N BIGINT);
INSERT INTO #NUMS
VALUES (3), (5), (7);
WITH R AS
(
SELECT N FROM #NUMS
UNION ALL
SELECT N*N AS N FROM R WHERE N*N < 10000000
)
SELECT N FROM R ORDER BY N;
살펴 보도록하겠습니다.
먼저 앵커 멤버가 실행되고 결과 세트가 R에 배치됩니다. 따라서 R은 {3, 5, 7}로 초기화됩니다.
그런 다음 실행이 UNION ALL 아래로 떨어지고 재귀 멤버가 처음으로 실행됩니다. R (즉, 현재 보유하고있는 R : {3, 5, 7})에서 실행됩니다. 결과적으로 {9, 25, 49}가됩니다.
이 새로운 결과로 무엇을합니까? 기존 {3, 5, 7}에 {9, 25, 49}를 추가하고 결과 조합 R에 레이블을 지정한 다음 재귀를 계속 수행합니까? 아니면 R을이 새로운 결과 {9, 25, 49}로 재정의하고 나중에 모든 노조를 수행합니까?
두 가지 선택 모두 의미가 없습니다.
R이 현재 {3, 5, 7, 9, 25, 49}이고 다음 재귀 반복을 실행하면 {9, 25, 49, 81, 625, 2401}로 끝나고 우리는 {3, 5, 7}을 잃었습니다.
R이 이제 {9, 25, 49} 인 경우 라벨 오류가 잘못되었습니다. R은 앵커 부재 결과 세트 및 모든 후속 재귀 부재 결과 세트의 합집합 인 것으로 이해된다. {9, 25, 49}는 R의 구성 요소 일뿐입니다. 지금까지 우리가 달성 한 전체 R은 아닙니다. 따라서 R에서 선택하는 것으로 재귀 멤버를 작성하는 것은 의미가 없습니다.
@Max Vernon과 @Michael S.가 아래에 자세히 설명한 내용에 감사드립니다. 즉, (1) 모든 구성 요소가 재귀 한계 또는 널 세트까지 작성되고 (2) 모든 구성 요소가 결합됩니다. 이것이 실제로 작동하는 SQL 재귀를 이해하는 방법입니다.
만약 우리가 SQL을 재 설계한다면, 다음과 같이보다 명확하고 명확한 문법을 시행 할 것입니다 :
WITH R AS
(
SELECT N
INTO R[0]
FROM #NUMS
UNION ALL
SELECT N*N AS N
INTO R[K+1]
FROM R[K]
WHERE N*N < 10000000
)
SELECT N FROM R ORDER BY N;
수학의 귀납적 증거와 같습니다.
현재 SQL 재귀의 문제점은 혼란스러운 방식으로 작성된다는 것입니다. 작성 방법에 따르면 각 구성 요소는 R에서 선택하여 구성되지만 지금까지 구성 된 전체 R을 의미하지는 않습니다. 단지 이전 구성 요소를 의미합니다.