Это особая проблема, с которой я сталкивался много раз,
но я так и не нашел простого решения этой (казалось бы) простой проблемы.
Как обеспечить, чтобы у данного родителя было фиксированное количество детей?
1) Пример.
Как сделать так, чтобы в определенном классе было, скажем, всего 50 учеников? ..
create table class(
class_id number primary key,
class_name varchar2(50),
class_attributes varchar2(50)
);
create table student(
student_id number primary key,
student_name varchar2(50),
student_attributes varchar2(50)
);
create table class_student_asc(
class_id number,
student_id number,
other_attributes varchar2(50),
constraint pk_class_student_asc primary key (class_id,student_id),
constraint fk_class_id foreign key (class_id) references class(class_id),
constraint fk_student_id foreign key (student_id) references student(student_id)
);
Это те реализации, о которых я знаю.
Дайте мне знать, какой из них вы бы предпочли, и если есть более простой способ добиться этого.
а)
Реализация с помощью триггеров на дочерней таблице (class_student_asc).
Запрос к той же таблице в перед вставкой, триггер обновления, чтобы получить количество.
Так как это приводит к ошибке таблицы мутаций, это делится на два разных уровня оператора
триггеры (оператор до и после) для достижения результата.
http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936
б) * * тысяча двадцать-одна
Включите переменную count в таблицу классов и заблокируйте родительскую запись для обновления перед вставкой записи в дочернюю таблицу.
Итак, что-то вроде ..
create table class(
class_id number primary key,
class_name varchar2(50),
class_attributes varchar2(50),
class_count INTEGER,
constraint chk_count_Students check (class_count <=5)
);
и вместо того, чтобы выставлять таблицу class_student_asc для вставок и так далее ...
написать процедуру, а затем использовать ее во всех приложениях ..
procedure assign_new_student(
i_student_id number,
i_class_id number)
is
begin
select class_count
from class
where class_id = i_class_id
for update ; -- or for update nowait, if you want the other concurrent transaction to fail..
insert into class_student_asc(
class_id, student_id)
values (i_class_id,i_student_id);
update class
set class_count = class_count + 1
where class_id = i_class_id;
commit;
end assign_new_student;
в)
Есть, конечно, случаи, когда у пользователя есть два адреса электронной почты.
В таком случае сам адрес электронной почты не имеет никакого атрибута
и таблица может быть такой простой, как
create table user_table
(
user_id number,
user_name varchar2(50),
user_email_primary varchar2(50),
user_email_secondary varchar2(50)
);
Однако мы не можем расширить тот же подход для вопроса, приведенного выше ....., поскольку количество столбцов и проверка ограничений будут замедлять вставки и обновления. Кроме того, это будет означать, что нам нужно будет добавлять новый столбец каждый раз, когда мы меняем правило ... тоже.
Пожалуйста, совет.