Взгляните к подсказке, выделенной к вставке/обновлению метки времени на vim.wikia.
CYCLE
упоминается «ряд предков». Однако, вообще говоря, в рекурсивном CTE
нет понятия «родительский ряд». Это операция, основанная на множестве, которая может давать результаты полностью вне дерева. Вообще говоря, часть привязки и рекурсивная часть могут даже использовать разные таблицы.
Поскольку рекурсивные CTE
обычно используются для построения деревьев иерархии, Oracle
решил добавить проверку цикла. Но из-за основанного на множестве способа работы рекурсивного CTE
, обычно невозможно сказать, будет ли следующий шаг генерировать цикл или нет, потому что без четкого определения условия цикла "родительская строка" невозможно
Чтобы выполнить «следующий» шаг, Однако у него нет никаких средств для обнаружения циклов, потому что циклы изначально не определены.
Как упоминалось ранее, MySQL
не реализует CTE
на все (он не реализует HASH JOIN
или MERGE JOIN
, а только вложенные циклы, так что не сильно удивляйтесь).
Как ни странно, я получил письмо сегодня по этой теме, о котором я расскажу в своем блоге.
Обновление:
Рекурсивные CTE
в SQL Server
не более чем СВЯЗАТЬСЯ С
замаскированным. См. Шокирующие подробности в этой статье в моем блоге:
MySQL Server версии 5.0.45 не понравилось с
:
ОШИБКА 1064 (42000): у вас есть ошибка в синтаксисе SQL; проверить руководство, соответствующее вашей версии сервера MySQL, для правильного синтаксис для использования рядом с 'с tr (id, parent_id) as (select id, parent_id из t, где id = 1, объединить все s 'в строке 1.
PostgreSQL supports WITH-style hierarchical queries, but doesn't have any automatic cycle detection. This means that you need to write your own and the number of rows returned depends on the way you specify join conditions in the recursive part of the query.
Both examples use an array if IDs (called all_ids) to detect loops:
WITH recursive tr (id, parent_id, all_ids, cycle) AS (
SELECT id, parent_id, ARRAY[id], false
FROM t
WHERE id = 1
UNION ALL
SELECT t.id, t.parent_id, all_ids || t.id, t.id = ANY(all_ids)
FROM t
JOIN tr ON t.parent_id = tr.id AND NOT cycle)
SELECT id, parent_id, cycle
FROM tr;
id | parent_id | cycle
----+-----------+-------
1 | 2 | f
2 | 1 | f
1 | 2 | t
WITH recursive tr (id, parent_id, all_ids, cycle) AS (
SELECT id, parent_id, ARRAY[id], false
FROM t
WHERE id = 1
UNION ALL
SELECT t.id, t.parent_id, all_ids || t.id, (EXISTS(SELECT 1 FROM t AS x WHERE x.id = t.parent_id))
FROM t
JOIN tr ON t.parent_id = tr.id
WHERE NOT t.id = ANY(all_ids))
SELECT id, parent_id, cycle
FROM tr;
id | parent_id | cycle
----+-----------+-------
1 | 2 | f
2 | 1 | t
AFAIK: