Как CTE работает внутри sql?

#sql-server #common-table-expression

#sql-сервер #common-table-expression

Вопрос:

У меня возникла проблема с отслеживанием последовательности выполнения следующего кода :

Код работает нормально

Я просто пытаюсь понять, как.

     with MyCTE(x)
    as
    (
  1)  select x = convert(varchar(8000),'hello') // line 1
    union all
  3)  select x   'a' from MyCTE where len(x) < 100 //line 3
    )
    select x from MyCTE
    order by x
 

MSDN:

Семантика рекурсивного выполнения выглядит следующим образом:

Разделите выражение CTE на якорные и рекурсивные члены.

Запустите привязочный элемент (ы), создающий первый вызов или базовый набор результатов (T0).

Запустите рекурсивный элемент (ы) с Ti в качестве входных данных и Ti 1 в качестве выходных данных.

Повторяйте шаг 3, пока не будет возвращен пустой набор.

Возвращает результирующий набор. Это ОБЪЕДИНЕНИЕ ВСЕХ значений от T0 до Tn.

Этапы:

1) выполняется строка 1 (x = привет)

2) выполняется строка 3 (привет)

3) теперь он называет себя так: здесь x снова возвращается к hello!! (строка 1)

  • согласно: строка 1, всякий раз, когда cte вызывает себя — x всегда должен быть сброшен! (или T0 обходится в рекурсивном?)
  • какова роль для (x) части, которую он выполняет в MyCTE (x)? ввод или вывод?

Цитата:

Запустите рекурсивный элемент (ы) с Ti в качестве входных данных и Ti 1 в качестве выходных данных.

Насколько мне известно, (x) — это значение out, а не Input.

Комментарии:

1. Это теоретический вопрос, или вы уже запускали это?

2. @gbn — Привет! , я уже запускаю это, и оно работает, но я не могу узнать, как. — whenever the cte calls itself - the x is always should be reset , но это не так (и это нормально), но я не могу понять, почему: он говорит каждый раз : select x = convert(varchar(8000),'hello')

Ответ №1:

T0 / Line1 выполняется один раз в качестве привязки.

  1. строка 1 выполнена (привет)
  2. строка 3 выполняется (helloa), потому что LEN(hello) = 5 меньше 100
  3. строка 3 выполняется (helloaa), потому что LEN(helloa) = 6 меньше 100
  4. строка 3 выполняется (helloaaa), потому что LEN(helloaa) = 7 меньше 100
  5. строка 3 выполняется (helloaaaa), потому что LEN(helloaaaa) = 8 меньше 100
  6. строка 3 выполняется (helloaaaaa), потому что LEN(helloaaaa) = 9 меньше 100
  7. строка 3 выполняется (helloaaaaaa), потому что LEN(helloaaaa) = 10 меньше 100

С некоторыми комментариями

 with MyCTE(x)
as
(
   select x = convert(varchar(8000),'hello')     -- Anchor, executed once
   union all
   select x   'a' from MyCTE where len(x) < 100  -- Recursion, executed n times
)
select x from MyCTE order by x
 

Во время выполнения это

    select x = convert(varchar(8000),'hello')     -- Anchor
   union all
   select 'hello'   'a'         -- Recursion 1
   union all
   select 'helloa'   'a'        -- Recursion 2
   union all
   select 'helloaa'   'a'       -- Recursion 3
   union all
   select 'helloaaa'   'a'      -- Recursion 4
   union all
   select 'helloaaaa'   'a'     -- Recursion 5
   ...
 

Комментарии:

1. Как всегда — ты ВЕЛИКОЛЕПЕН. Спасибо. проблема заключалась в том, что я думал, что эта строка 1 ВСЕГДА выполняется….