Рекурсивные запросы

advertisement
Рекурсивные запросы в Oracle
Фёдоров Р.К.
Рекурсивные запросы
• Рекурсивные запросы используются для
обращения к иерархически связанным
данным.
• create table test_table (
id number(6),
pid number(6),
title varchar2(256)
);
test_table
Иерархическая организация данных
• Большинство современных СУБД (Система
Управления Базами Данных) —
реляционные, т.е. представляют данные в
виде двумерной таблицы, в которой есть
строки (записи) и столбцы (поля записей).
Но на практике мы часто сталкиваемся с
иной организацией данных, а именно
иерархической.
Примеры
• Список файлов на компьютере: все они
организованы в виде дерева.
• Книги в библиотеке: Библиотека->Зал->Шкаф>Полка->Книга.
• Статьи на сайте: Сайт->Раздел->Подраздел->Статья.
Можно разделить все на отдельные таблицы:
таблица для хранения списка библиотек, другая
таблица для списка залов, третья для шкафов и т.д.
Но если заранее не известна глубина вложенности
или эта вложенность может меняться, тут уж от
иерархии никак не отмашешься.
• Данные, имеющие иерархическую
структуру, очень плохо представляются в
реляционной модели. В стандарте SQL-92
нет средств для их обработки.
• В Oracle иерархические запросы появились
в 8-ой версии, задолго до появления
стандарта. Поэтому до сих пор используется
совсем другой синтаксис.
START WITH
• Необязательный оператор START
WITH говорит Ораклу с чего начинать
рекурсию, т.е. какая строка (или строки)
будет корневой. Условие может быть
практически любым, можно даже
использовать функции или внутренние
запросы: pid is null, или id = 1, или даже
substr(title, 1, 1) = ‘Р’.
CONNECT BY
• Задает отношение между родительскими и
дочерними строками в иерархии. Отношение
задается условием, это может быть любое
сравнение, но какая-то его часть должна
содержать ключевое слово PRIOR,
относящееся к родительской строке.
• Каждая дочерняя строка должна
удовлетворять условию в фразе CONNECT
BY по отношению к одной из корневых строк.
PRIOR
• Для задания отношения родитель –
ребенок нужно использовать специальный
оператор, который называется PRIOR. С его
помощью можно написать правило pid =
PRIOR id.
Выбрать фамилии всех прямых начальников
сотрудника по фамилии ADAMS
• SELECT id, last_name, manager_id FROM
employee CONNECT BY PRIOR manager_id=id
START WITH last_name= 'ADAMS'
Псевдостолбец LEVEL
• Возвращает уровень записи по отношению
к корневой. Так, 1-ая запись будет иметь
уровень 1, ее потомки уровень 2, потомки
потомков — 3 и т.д.
Сортировка в пределах уровня
иерархии
• ORDER SIBLINGS BY <выражение>
• Пример
• SELECT lpad(' ', 3*level)||title as Tree
FROM test_table
START WITH pid is null
CONNECT BY PRIOR id = pid
ORDER SIBLINGS BY title;
Вывод пути
• SYS_CONNECT_BY_PATH()
SELECT SYS_CONNECT_BY_PATH(title, '/')
as Path FROM test_table WHERE id=9
START WITH pid is null CONNECT BY PRIOR id =
pid;
Псевдостолбец CONNECT_BY_ISLEAF
• В этом псевдостолбце напротив каждой
строки проставляется 0 или 1. Если есть
потомки – проставится 0. Если потомков
нет, такой узел в дереве называется
“листом”, тогда и значение в поле
CONNECT_BY_ISLEAF будет равно 1.
Псевдостолбец CONNECT_BY_ROOT
• Ссылается на корневую запись, т.е. на
самую первую в выборке.
SELECT id, pid,
title, level, CONNECT_BY_ISLEAF as IsLeaf,
PRIOR title as Parent,
CONNECT_BY_ROOT title as Root
FROM test_table START WITH pid is null
CONNECT BY PRIOR id = pid
ORDER SIBLINGS BY title;
Результат
Используемые материалы
• http://habrahabr.ru/post/43955/
Download