Що стосується 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}.
Що це стосується цього нового результату? Чи додається він {9, 25, 49} до існуючого {3, 5, 7}, позначає отриманий об'єднання 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 не має сенсу.
Я, безумовно, ціную те, що @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, який був побудований (або, здається, був побудований) до цього часу. Це просто означає попередній компонент.