Шрифт:
CREATE TABLE PARENT_CHILD (
ID INTEGER NOT NULL,
PARENT_ID INTEGER
CHECK (PARENT_ID <> ID));
COMMIT;
ALTER TABLE PARENT_CHILD
ADD CONSTRAINT PK_PARENT
PRIMARY KEY(ID);
COMMIT;
ALTER TABLE PARENT_CHILD
ADD CONSTRAINT FK_CHILD_PARENT
FOREIGN KEY(PARENT_ID)
REFERENCES PARENT_CHILD(ID);
Можно было бы сказать гораздо больше о проектировании древовидных структур. Это перспективная тема в создании реляционных баз данных, которая расширяет
границы стандарта SQL. К сожалению, она выходит за рамки данной книги. Некоторые интересные решения см. в "SQL for Smarties", 2nd Edition by Joe Celko (Morgan Kaufmann, 1999).
Обязательные отношения
Обязательное отношение - это отношение, которое требует существования как минимум одной дочерней строки для каждой родительской строки. Например, структура накладной (заголовок с информацией о покупателе и адресом поставки) будет нелогичной, если будет разрешено существование заголовочной строки без детальных строк.
Общей ошибкой начинающих является предположение, что ограничение NOT NULL в дочерней таблице сделает отношение один-ко-многим обязательным. Этого не будет, потому что ограничение внешнего ключа действует только в контексте конкретной зависимости. В случае отсутствия строки, ссылающейся на родительскую таблицу, допустимость пустого значения для внешнего ключа не решает проблему.
Обязательное отношение - это одно из тех мест, где определенные пользователем триггеры должны быть использованы для поддержания ссылочной целостности. SQL в Firebird не поддерживает "обязательных" ограничений. Он может использовать некоторую логику на клиенте и на сервере для гарантирования правильной последовательности событий, которая бы соответствовала и ссылочному ограничению, и требованиям обязательности. Он будет использовать триггеры как для добавления, так и для удаления данных, поскольку эта логика должна поддерживать правило "минимально один потомок" не только во время создания, но и при удалении дочерних строк.
Подробности написания триггеров, а также пример триггера для поддержания обязательного отношения см. в главе 31.
Ошибка "объект находится в использовании"
Исключение "object is in use" (объект находится в использовании) заслуживает внимания в контексте применения ограничений ссылочной целостности, поскольку является постоянным источником огорчений для новичков. Firebird не позволяет добавлять или удалять ссылочное ограничение FOREIGN KEY, если транзакция использует любую из участвующих таблиц.
Иногда для вас может быть не столь очевидным, каким образом объект находится в использовании. Другие зависимости - такие как хранимые процедуры или триггеры, которые ссылаются на ваши таблицы, или другие ссылочные ограничения, воздействующие на одну или обе таблицы - могут вызвать это исключение, если таблицы используются в неподтвержденной транзакции. Кэш метаданных (блоки памяти на сервере, которые содержат метаданные, сформированные в результате выполнения последних клиентских запросов, и коды вызванных хранимых процедур и триггеров) хранит блокировки применяемых объектов. Каждое соединение имеет свой собственный кэш метаданных, даже в случае Суперсервера, следовательно, сервер может хранить блокировки объектов, которые фактически не используют ни одно соединение.
Настоятельно рекомендуется получить исключительный доступ к базе данных для любых изменений метаданных, особенно тех, которые используют зависимости.
! ! !
СОВЕТ. Если вы имеете исключительный доступ, а исключение все равно появляется, то вполне возможно, что объект используете именно вы. Если вы работаете с утилитой администратора, где браузер данных сфокусирован на одной из ваших таблиц, то этот объект находится в использовании!
. ! .
Firebird использует индексы для поддержания ссылочной целостности. При этом индексы играют такую же важную роль в оптимизации производительности при операциях поиска и упорядочения, требуемых для запросов и для изменения данных. В следующей главе мы рассмотрим в полном объеме вопросы проектирования, создания и тестирования индексов. Глава заканчивается специальным разделом, посвященным оптимизации индексов с использованием Firebird-утилиты получения статистики по индексам gstat.
ГЛАВА 18. Индексы.
Индексы являются атрибутами таблицы, которые могут содержать один столбец или группу столбцов для ускорения поиска строк.
Индекс служит логическим указателем на физическое размещение (адрес) строк в таблице; он используется почти так же, как вы применяете указатель в книге для быстрого поиска номеров страниц разделов, которые вы собираетесь просмотреть. В большинстве случаев, если сервер может прочесть запрашиваемые строки, сканируя индекс вместо сканирования всех строк в таблице, запросы будут выполняться быстрее. Хорошо спроектированная система индексов играет важную роль в настройке и оптимизации условий эксплуатации ваших приложений.