В идеальном мире ваша СУБД по вашему выбору будет реляционно полной, что позволит вам писать ограничения произвольной сложности и поддерживать множественное присваивание, чтобы позволить вашей базе данных постоянно обновляться (т.е. без откладывания или отключения ограничений), используя простые операторы,В реальном мире у нас есть SQL.
Идеальный продукт SQL будет соответствовать стандарту Full SQL-92: поддерживать CREATE ASSERTION
(ограничения уровня схемы), разрешать подзапросы в ограничениях CHECK
и поддерживать отсрочкуограничения внутри транзакции, позволяющие обновлять базу данных без отключения ограничений.К сожалению, Oracle еще не достигла такого уровня функциональности.Поэтому в реальном мире нам иногда приходится прибегать к процедурному коду для «управления» обновлениями при сохранении целостности данных.
Рассмотрим, например, истинные отношения один к одному, достаточно распространенные, с бизнес-правилами.следующим образом:
База данных содержит сведения о сотрудниках и проектах в трех версиях: EMP, PROJ и EMP_PROJ.В каждом проекте должен быть хотя бы один сотрудник, и каждое вложение проекта должно относиться к существующему проекту.Когда проект создается, к нему должен быть одновременно подключен как минимум один сотрудник.
В Oracle нельзя написать ASSERTION
или CHECK
для применения ограничений между таблицами, поэтомув этом случае способность откладывать ограничения не имеет большого значения.
Один из подходов, который может помочь написать PROCEDURE
с соответствующими параметрами для создания проекта и назначения одного сотрудника для проекта.Такая процедура должна в следующем порядке (псевдокод):
1) начинать транзакцию;
2) вставлять в PROJ
;
3) вставлять в EMP_PROJ
;
4) Проверка данных, которые не соответствуют условным ограничениям, например,
EXISTS (
SELECT *
FROM PROJ
WHERE NOT EXISTS (
SELECT *
FROM EMP_PROJ
WHERE EMP_PROJ.project_code = PROJ.project_code
)
);
5) Если при проверке обнаруживаются недопустимые данные, в противном случае выполняется откат транзакции.
Если ограничения кусаются, то транзакция откатывается и целостность данных сохраняется (хотя, возможно, вы захотите обработать такой сбой проверки более изящно:)
Аналогичная процедура потребуется для удаления сотрудника изпроект по предотвращению сценария, когда последний оставшийся назначенный сотрудник удаляется из проекта (следует ли исключить удаление сотрудника или следует удалить проект? спросите своего дизайнера:)
Поскольку целостность данных может быть обеспечена тольковыполняя такой процедурный код, удобно для всех инкапсулировать его в объекте PROCEDURE
в базе данных, а затем предоставить 'execute' pдарит пользователям PROCEDURE
(вместо предоставления расширенных привилегий для базовых таблиц).Чтобы заставить группу пользователей (например, приложения конечного пользователя) использовать только PROCEDURE
для обновления данных, их права на обновление для базовых таблиц должны быть аннулированы.Это может потребовать предоставления дополнительных «вспомогательных» функций, например, для назначения сотрудников на проект и удаления проекта.Если вы купите в школе «все доступ к базе данных через хранимые процедуры», вы все равно будете этим заниматься.