26 мая 2010 г.

Как избежать циклических кольцевых ссылок в реляционной базе данных?

Системная таблица RDB$DEPENDENCIES хранит связи между метаданными в базе. Попытка вытянуть все зависимости для заданного объекта с помощью WITH RECURSIVE в общем случае разбивается о бесконечные циклы. Можно ли решить задачу одним запросом исходя из существующей структуры RDB$DEPENDENCIES? Ничего лучше, чем контролировать уровень вложенности и прерывать поиск при достижении заданной глубины, пока не приходит в голову:

WITH RECURSIVE dep_tree AS (
  SELECT
    0 as lvl, 
    rdb$dependent_name, 
    rdb$dependent_type, 
    rdb$depended_on_name
  FROM
    rdb$dependencies
  WHERE
    rdb$depended_on_name = :depname
  UNION ALL
  SELECT
    (t.lvl + 1) as lvl, 
    d.rdb$dependent_name, 
    d.rdb$dependent_type, 
    d.rdb$depended_on_name
  FROM
    rdb$dependencies d JOIN dep_tree t 
      ON t.rdb$dependent_name = d.rdb$depended_on_name
        AND t.lvl < 5 )
SELECT DISTINCT 
  rdb$dependent_name, 
  rdb$dependent_type, 
  rdb$depended_on_name
FROM
  dep_tree

Глубину прекращения поиска мы задаем вручную (в примере -- это константа 5). Если задать слишком много, то запрос будет выполняться слишком долго. Задать мало -- и мы рискуем потерять объекты при большой глубине вложенности связей.

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

Отправить комментарий