Oracle - Как применять правила для отношений в зависимости от атрибутов записей (простой пример) - PullRequest
2 голосов
/ 29 апреля 2011

В школьной системе у меня есть 2 таблицы, одна называется «Персонал», в которой хранятся записи всех сотрудников школы, учителей, администраторов, поваров, уборщиков и т. Д. Затем у меня есть вторая таблица «Курс» с внешним ключом, относящимся к Персонал, чтобы указать, кто является руководителем курса, теперь я хочу только позволить учителям быть руководителем курса, то есть повар не может быть, но я не уверен, как это ограничить на уровне базы данных.

Примечание: здесь я задал более сложный неправильный вопрос - Oracle Unique Constraint - триггер для проверки значения свойства в новом отношении

Ответы [ 5 ]

1 голос
/ 29 апреля 2011

Вы можете проверить это ограничение в триггере после вставки или обновления на curses tabelle.

CREATE or replace TRIGGER check_leader
AFTER INSERT OR UPDATE ON  Course
FOR EACH ROW
declare
  v_type varchar2(30);
BEGIN
  select type into v_type from stuff where :NEW.leader_id = stuff.stuff_id;
  if v_type != 'teacher' then 
   RAISE_APPLICATION_ERROR(-20000, 'course leader must be teacher');
  end if;
end;
/

Но вам нужен еще один триггер на столе персонала. В случае смены типа материала (с учителя на уборщика) необходимо проверить наличие записей в таблице проклятий.

CREATE or replace TRIGGER check_courses
AFTER UPDATE ON  STUFF
FOR EACH ROW
declare
  v_num number;
BEGIN
  if :OLD.type = 'teacher' and :NEW.type != 'teacher' then
     select count(*) into v_num from curses where courses.leader_id = :NEW.stuff_id;
     if v_num > 0 then 
       RAISE_APPLICATION_ERROR(-20000, 'there are courses assigned ');
      end if;
  end if;
end;
/
0 голосов
/ 30 апреля 2011

В этом сценарии я бы пересмотрел модель данных.Я бы взял обобщенную таблицу staff и добавил бы под ней таблицы для каждого STAFF_TYPE: CATERERS, TEACHERS, ADMIN и т. Д. Тогда просто применить внешний ключ между COURSES и TEACHERS без необходимости триггеров.* Это стандартное решение проблемы такого рода.По мере дальнейшего изучения требований вы обнаружите, что с поварами и уборщиками будут возникать аналогичные проблемы с внешними ключами.Также вероятно, что вы обнаружите, что у учителей есть атрибуты, которых нет у администраторов.Вот почему отдельные таблицы для каждого типа полезны.В то же время у них всех есть что-то общее.Вот почему вам нужен стол для супер типа STAFF.


Конечно, предлагая этот ответ, я повторяю предложение @ 1006 * ДжеффриКемпа в вашем предыдущем вопросе .Ну, а @RobVanWijk заимствовал мою , почему бы и нет?:)

0 голосов
/ 30 апреля 2011

Я не вижу смысла делать это на уровне базы данных или, по крайней мере, усложнять вашу жизнь с помощью триггеров и т. Д.

Просто создайте эти объекты:

  • таблица с именем STAFF, которая имеет поле типа (тип может быть НЕДЕЙСТВИТЕЛЕН или ЛИДЕР КУРСА)
  • таблица с именем COURSE, которая имеет внешний ключ для STAFF
  • представление с именем COURSE_LEADERS, то есть select * from STAFF, где type = "COURSE LEADER"

Затем при работе с курсами и их руководителями используйте только объекты COURSE и COURSE_LEADERS в своем приложении. Так просто.

0 голосов
/ 29 апреля 2011

Вы можете сделать это, как сказал APC в другом потоке.

Вот пример:

SQL> create table staff
  2  ( id         number(10)   not null primary key
  3  , name       varchar2(10) not null
  4  , staff_type varchar2(10) not null check (staff_type in ('TEACHER','COOK','ADMIN','CLEANER'))
  5  , constraint staff_uk unique (id,staff_type)
  6  )
  7  /

Table created.

SQL> insert into staff values (1, 'ALAN', 'COOK')
  2  /

1 row created.

SQL> insert into staff values (2, 'BOB', 'TEACHER')
  2  /

1 row created.

SQL> create table course
  2  ( id         number(10)   not null primary key
  3  , name       varchar2(30) not null
  4  , staff_id   number(10)   not null
  5  , staff_type varchar2(10) default 'TEACHER' not null
  6  , constraint course_staff_fk
  7      foreign key (staff_id,staff_type)
  8      references staff (id,staff_type)
  9  )
 10  /

Table created.

SQL> insert into course (id,name,staff_id) values (1, 'Mathematics', 1)
  2  /
insert into course (id,name,staff_id) values (1, 'Mathematics', 1)
*
ERROR at line 1:
ORA-02291: integrity constraint (SCHEMA.COURSE_STAFF_FK) violated - parent key not found


SQL> insert into course (id,name,staff_id) values (2, 'Physics', 2)
  2  /

1 row created.

С уважением,
Роб.

0 голосов
/ 29 апреля 2011

Вы можете добавить еще одну таблицу с именем COURSE_LEADERS, чтобы отслеживать всех, кто в настоящее время может вести курс, затем иметь отношение от COURSE до COURSE_LEADERS, а также отношение от COURSE_LEADER до STAFF , Таким образом, повар может вести курс только в том случае, если он находится в COURSE_LEADER, но если это курс о приготовлении пищи, может, это нормально ...? ;)

Этот метод, конечно, означает, что должен быть какой-то способ добавить / удалить сотрудников из course_leader. Если вы хотите, чтобы он был автоматическим, у вас может быть триггер, который вставляет запись в COURSE_LEADER, когда добавляется новый STAFF, если персонал является учителем - при условии, что можно определить, является ли персонал учителем, когда его сотрудники запись вставлена.

...