oracle(或任何关系)数据模型问题.有固定数量的孩子的父母?

Raj*_*thi 5 sql oracle plsql data-modeling

这是我多次遇到的一个特殊问题,但我从来没有真正找到一个简单的解决方案来解决这个看似简单的问题.

如何确保给定的父母有固定数量的孩子?

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)
);
Run Code Online (Sandbox Code Playgroud)

这些是我所知道的实现.让我知道您更喜欢哪一个,以及是否有更简单的方法来实现这一目标.

一个)

在子表(class_student_asc)上使用触发器实现它.

在插入前查询同一个表,更新触发器以获取计数.由于这会给出变异表错误,因此将其拆分为两个不同的语句级触发器(before-statement和after-statement)以实现结果.

http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936

b)

在类表中包含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)
);
Run Code Online (Sandbox Code Playgroud)

而不是暴露表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;
Run Code Online (Sandbox Code Playgroud)

C)

当然,有一些用户有两个电子邮件地址的情况.在这种情况下,电子邮件地址本身没有任何属性,表格可能很简单

create table user_table
          (
            user_id number,
            user_name varchar2(50),
            user_email_primary varchar2(50),
            user_email_secondary varchar2(50)
          );
Run Code Online (Sandbox Code Playgroud)

但是,我们无法对上述问题扩展相同的方法.....因为列数和约束检查会减慢插入和更新的速度.此外,这意味着我们每次更改规则时都需要添加新列.

请指教.

Jan*_*cki 5

对于Oracle,请考虑这种方法.

创建一个实体化视图,总结每个班级的学生人数.让mview在提交时刷新,并为mview添加一个约束,禁止每班超过50名学生.

此代码演示了如何在提交mview上使用快速刷新来强制执行学生计数限制,

insert into class(class_id, class_name) values (1, 'Constraints 101');
insert into class(class_id, class_name) values (2, 'Constraints 201');
insert into student(student_id, student_name) values(1, 'Alice');
insert into student(student_id, student_name) values(2, 'Bob');
insert into student(student_id, student_name) values(3, 'Carlos');

create materialized view log on class_student_asc with primary key, rowid, sequence including new values;

create materialized view class_limit refresh fast on commit as
  select class_id, count(*) count from class_student_asc group by class_id;

alter table class_limit add constraint class_limit_max check(count <= 2);

insert into class_student_asc(class_id, student_id) values(1, 1);
insert into class_student_asc(class_id, student_id) values(1, 2);
insert into class_student_asc(class_id, student_id) values(1, 3);
Run Code Online (Sandbox Code Playgroud)

提交事务时将违反约束,而不是在第三个学生被添加到课程时.这可能会对您的应用程序代码产生影响.SQL Developer无法显示错误,但sql*plus确实显示错误.

替代文字http://i27.tinypic.com/5ajplw.png