BPwin и Erwin. CASE-средства для разработки информационных систем - Маклаков Сергей Владимирович. Страница 21
Рис. 2.27. Случай обязательности имен ролей
Другим примером обязательности присвоения имен ролей являются рекурсивные связи (иногда их называют "рыболовный крючок" - fish hook), когда одна и та же сущность является и родительской и дочерней одновременно. При задании рекурсивной связи атрибут должен мигрировать в качестве внешнего ключа в состав неключевых атрибутов той же сущности. Атрибут не может появиться дважды в одной сущности под одним именем, поэтому обязательно должен получить имя роли. На рис. 2.26 сущность Сотрудник содержит атрибут первичного ключа Табельный номер. Информация о руководителе сотрудника содержится в той же сущности, поскольку руководитель работает в той же организации. Чтобы сослаться на руководителя сотрудника следует создать рекурсивную связь (на рис. 2.26 связь руководит/подчиняется) и присвоить имя роли ("Руководитель"). Заметим, что рекурсивная связь может быть только неидентифицирующей. В противном случае внешний ключ должен был бы войти в состав первичного ключа и получить при генерации схемы признак NOT NULL. Это сделало бы невозможным построение иерархии - у дерева подчиненности должен быть корень - сотрудник, который никому не подчиняется в рамках данной организации.
Связь руководит/подчиняется на рис. 2.26 позволяет хранить древовидную иерархию подчиненности сотрудников. Такой вид рекурсивной связи называется иерархической рекурсией (hierarchical recursion) и задает связь, когда руководитель (экземпляр родительской сущности) может иметь множество подчиненных (экземпляров дочерней сущности), но подчиненный имеет только одного руководителя (рис. 2.28).
Иерархическая рекурсия Сетевая рекурсия
Рис. 2.28. Подчиненность экземпляров сущности в иерархической и сетевой рекурсии
Другим видом рекурсии является сетевая рекурсия (network recursion), когда руководитель может иметь множество подчиненных и, наоборот, подчиненный может иметь множество руководителей. Сетевая рекурсия задает паутину отношений между экземплярами родительской и дочерней сущностей. Это случай, когда сущность находится сама с собой в связи многие-ко-многим. Для разрешения связи многие-ко-многим необходимо создать новую сущность (подробно связь многие-ко-многим будет рассмотрена ниже).
Рис. 2.29. Пример реализации сетевой рекурсии
На рис. 2.29 рассмотрен пример реализации сетевой рекурсии. Структура моделирует родственные отношения между членами семьи любой сложности. Атрибут Тип отношения может принимать значения "отец-сын", "мать-дочь", "дед-внук", "свекровь-невестка", "тесть-зять" и т. д. Поскольку родственное отношение связывает всегда двух людей, от сущности Родственник к. сущности Родственное отношение установлены две идентифицирующие связи с именами ролей "Старший" и "Младший". Каждый член семьи может быть в родственных отношениях с любым другим членом семьи, более того, одну и ту же пару родственников могут связывать разные типы родственных отношений.
Если атрибут мигрирует в качестве внешнего ключа более чем на один уровень, то на первом уровне отображается полное имя внешнего ключа (имя роли + базовое имя атрибута), на втором и более - только имя роли. На рис. 2.30 изображена структура данных, которая содержит сущность Команда, сущность Игрок, в которой хранится информация об игроках каждой команды, и сущность Гол, содержащая информацию и голах, которые забивает каждый игрок. Атрибут внешнего ключа Номер команды сущности Игрок имеет имя роли "В какой команде играет".
Рис. 2.30. Миграция имен ролей
На следующем уровне, в сущности Гол, отображается только имя роли соответствующего атрибута внешнего ключа (В какой команде играет).
Правила ссылочной целостности (referential integrity, RI) - логические конструкции, которые выражают бизнес-правила использования данных и представляют собой правила вставки, замены и удаления. При генерации схемы БД на основе опций логической модели, задаваемых в закладке Rolename/RI Actions, будут сгенерированы правила декларативной ссылочной целостности, которые должны быть предписаны для каждой связи, и триггеры, обеспечивающие ссылочную целостность. Триггеры представляют собой программы, выполняемые всякий раз при выполнении команд вставки, замены или удаления (INSERT, UPDATE или DELETE). На рис. 2.30 существует идентифицирующая связь между сущностями Команда и Игрок. Что будет, если удалить команду? Экземпляр сущности Игрок не может существовать без команды (атрибут первичного ключа В какой команде играет. Номер команды не может принимать значение NULL), следовательно, нужно либо запретить удаление команды, пока в ней числится хотя бы один игрок (для удаления команды сначала нужно удалить всех игроков), либо сразу удалять вместе с командой всех ее игроков. Такие правила удаления называются "ограничение" и "каскад" (Parent RESTRICT и Parent CASCADE, см. рис. 2.25). Заметим, что сущности Игрок и Гол, в свою очередь, тоже связаны идентифицирующей связью и в случае удаления каскадом команды будут удалены все игроки команды и все голы, которые они забивали. Выполнение команды на удаление одной строки реально может привести к удалению тысячи строк в БД, поэтому использовать правило удаления каскадом следует с осторожностью. В том случае, если установлено правило ограничения удаления, при попытке выполнить удаление команды, в которой есть хотя бы один игрок, сервер реляционной СУБД возвратит ошибку.
На рис. 2.26 установлена необязательная неидентифицирующая связь между сущностями Отдел и Сотрудник. Экземпляр сущности Сотрудник может существовать без ссылки на отдел (атрибут внешнего ключа Где работает. Номер отдела может принимать значение NULL). В этом случае возможно установление правила установки в нуль - SET NULL. При удалении отдела атрибут внешнего ключа сущности Сотрудник - Где работает. Номер отдела примет значение NULL. Это означает, что при удалении отдела сотрудник остается работать в организации не будучи приписан к какому-либо отделу и информация о нем сохраняется.
Возможна установка еще двух правил удаления (если таковые поддерживаются СУБД):
SET DEFAULT - при удалении атрибуту внешнего ключа присваивается значение по умолчанию. Например, при удалении команды игроки могут быть переведены в другую команду.
NONE - при удалении значение атрибута внешнего ключа не меняется. Запись об игроке "повисает в воздухе", т. е. ссылается на несуществующую уже команду. Такая ситуация характерна для "плоских" таблиц. Например, если информация об игроках и командах хранится в dbf-файлах, можно удалить запись о команде, при этом файл игроков "ничего не будет знать" о том, что соответствующей команды не существует. Поэтому в настольных или файл-серверных системах функциональность, обеспечивающая правила ссылочной целостности, реализуется в клиентском приложении.
Правила удаления управляют тем, что будет происходить в БД при удалении строки. Аналогично правила вставки и обновления управляют тем, что будет происходить с БД, если строки изменяются или добавляются. Например, можно установить правило, которое разрешает вносить новую команду только в том случае, когда в нее зачислен хотя бы один игрок. Желаемое поведение может быть достигнуто следующими действиями: