Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
Шрифт:
CREATE TABLE COLORS (COLOR CHARACTER(20) NOT NULL PRIMARY KEY);
Фрагмент DDL одной из таблиц, которая использует COLORS В качестве таблицы соответствия:
CREATE TABLE STOCK_ITEM (
. . .
COLOR CHARACTER(20) DEFAULT 'NEUTRAL',
. . .
CONSTRAINT FK_COLOR FOREIGN KEY (COLOR)
REFERENCES COLORS(COLOR)
ON UPDATE CASCADE
ON DELETE SET DEFAULT;
Существует множество проблем с этим ключом. Во-первых, таблица COLORS была доступна покупателям товаров для ее редактирования, как они считали нужным. Изменения выполнялись каскадно по всей системе всякий раз, когда новые элементы добавлялись
"Реляционный путь" - устранение незапланированных нарушений данных за счет использования ключа соответствия, который будет содержать не имеющие смысл данные (т. е. атомарный ключ):
CREATE TABLE COLORS (
ID INTEGER NOT NULL PRIMARY KEY, /* or UNIQUE */
COLOR CHARACTER(20));
COMMIT;
INSERT INTO COLORS (ID, COLOR)
VALUES (0, 'NEUTRAL');
COMMIT;
CREATE TABLE STOCK_ITEM (
. . .
COLOR INTEGER DEFAULT 0,
. . .);
Такой ключ никогда не нужно изменять; он может (и должен) быть спрятан от пользователей. Таблицы, использующие таблицы соответствия, хранят стабильный ключ. Все допустимые изменения реализуются как новые строки таблицы соответствия с новыми ключами. Значения, уже связанные с ключами, не изменяются- они защищены от того, чтобы история данных подвергалась риску последующих изменений.
В этом случае, даже при большом распределении значений ключа внешний ключ будет создавать индекс, который все еще будет иметь плохую селективность в большой таблице; повышение стабильности таблицы оправдывает отказ от формального ссылочного ограничения. Существование строки с соответствующим первичным ключом легко можно проверить с помощью пользовательского триггера.
Привилегии на ссылки
Firebird поддерживает безопасность SQL для всех объектов в базе данных. Каждый пользователь, за исключением владельца базы данных, пользователя SYSDBA или с системными привилегиями root, должен получить (при использовании GRANT) необходимые привилегии доступа к объекту. Привилегии SQL очень подробно обсуждаются в главе 3 7.
Тем не менее одна привилегия очень важна при проектировании инфраструктуры ссылочной целостности - привилегия REFERENCES. ЕСЛИ родительская и дочерняя таблицы имеют разных владельцев, привилегия GRANT REFERENCES может оказаться необходимой для предоставления пользователям достаточных полномочий для действий ссылочного ограничения.
Привилегия REFERENCES предоставляется для таблицы, на которую осуществляется ссылка в отношении, - т. е. для таблицы, на которую ссылается внешний ключ, - или, по крайней мере, на каждый столбец первичного или уникального ключа. Привилегия должна быть предоставлена для владельца ссылающейся таблицы (дочерней таблицы), а также для любого пользователя, которому необходимы права записи на ссылающуюся таблицу.
Во время выполнения REFERENCES срабатывает, когда сервер базы данных устанавливает, что вводимое во внешний ключ значение находится в таблице, на которую осуществляется ссылка.
Поскольку такая привилегия проверяется при определении ограничения внешнего ключа, необходимо предоставить и подтвердить соответствующие разрешения заблаговременно. Если вам нужно создать внешний ключ, который ссылается на таблицу, которой владеет кто-то другой, то владелец должен предоставить вам привилегии REFERENCES к этой таблице. Альтернативно владелец может предоставить привилегии REFERENCES роли,
! ! !
СОВЕТ. Не делайте это сложнее, чем оно должно быть. Если нет никакого требования отменять привилегии чтения для таблицы, на которую осуществляются ссылки, то передайте привилегию REFERENCES К ней для всех (PUBLIC).
. ! .
Если ваши требования содержат такие ограничения, вам может понадобиться поддерживать два разрешающих скрипта: один для разработчиков, выполняющих создание таблицы, и другой для пользователей, работающих с созданной схемой.
Обработка других видов отношений
Ограничения целостности могут быть применены для других форм отношений, помимо формы один-ко-многим, описанной до настоящего времени.
* Один-к-одному.
* Многие-ко-многим.
* Ссылающееся на себя отношение один-ко-многим (вложенные или древовидные отношения).
* Обязательные варианты любых форм отношений.
Отношение один-к-одному
Структуры один-к-одному могут быть полезными, когда сущность в вашей модели данных имеет множество различных атрибутов, из которых только к некоторым часто осуществляется доступ. Это может резко сократить занимаемую память и время чтения страниц, если хранить случайные данные в необязательных "подчиненных" отношениях, которые используют соответствующие первичные ключи.
Отношение один-к-одному похоже на отношение один-ко-многим в том смысле, что оно связывает внешний ключ с уникальным ключом. Разница здесь в том, что связываемый ключ должен быть уникальным для поддержания отношения один-к-одному - чтобы соединить не более одной зависимой строки с одной родительской строкой.
Обычным является дублирование столбца (столбцов) первичного ключа в подчиненной таблице в качестве внешнего ключа для "родительской".
CREATE TABLE PARENT_PEER (
ID INTEGER NOT NULL,
MORE_DATA VARCHAR(10),
CONSTRAINT PK_PARENT_PEER PRIMARY KEY(ID),
CONSTRAINT FK_PARENT_PEER_PARENT
FOREIGN KEY (ID) REFERENCES PARENT);
Результатом такого дублирования является создание двух обязательных индексов для столбца первичного ключа подчиненной таблицы: один для первичного ключа и один для внешнего ключа. Индекс внешнего ключа сохраняется так, как если бы он не был уникальным.
В версиях 1.0.x и 1.5 оптимизатор игнорирует первичный индекс подчиненной таблицы. Например:
SELECT PARENT.ID, PARENT_PEER.ID,
PARENT.DATA, PARENT_PEER.MORE_DATA
FROM PARENT JOIN PARENT_PEER
ON PARENT.ID = PARENT_PEER.ID;
игнорирует индекс первичного ключа подчиненной таблицы и создает план:
PLAN JOIN (PARENT_PEER NATURAL, PARENT INDEX (PK_PARENT) )
Влияние на производительность "разреженного" ключа (такого, какой использован в этом примере) не может быть сильным. В случае составного ключа эффект может быть значительным, особенно в случае множественных соединений, включающих отношения один-к-одному. Следует рассмотреть использование суррогатного ключа в структурах один-к-одному [51] .
51
И надеяться, что эта маленькая причуда оптимизатора с ключами один-к-одному будет разрешена в следующих релизах.