Oracle SQL,寻找关于约束的想法

时间:2011-10-17 04:31:17

标签: sql oracle constraints

我有一个包含Class,Teacher和Leader行的表,

Class和Teacher是Numbers,Leader是一个布尔值(实际上只是一个Char(1))

该表代表教师与班级之间的关系。

一个班级可以有很多老师,或者教师可以有很多班级。

我需要制作一个约束或检查,以便对于每个不同的类,它出现的一个,只有一个行必须将Leader设为true。

例如

Teacher |  Class | Leader
   1    |    1   |  True
   2    |    1   |  False
   2    |    2   |  True

将被接受,因为每个不同的类都有一行,其中Leader值为true,但不超过一行。

如果有人能提出如何将此作为约束来表达的想法,我将不胜感激。

5 个答案:

答案 0 :(得分:8)

创建基于函数的索引很容易,该索引强制执行约束的“不超过一个领导”部分

CREATE UNIQUE INDEX one_leader_per_class
    ON your_table_name( (CASE WHEN leader = 'Y' 
                              THEN class
                              ELSE null
                          END) );

不幸的是,创建一个声明性约束来强制要求每个类都有一个领导者并不容易。我知道这样做的唯一声明方式是创建一个物理化视图,按类聚合数据,将物化视图设置为REFRESH FAST,并在物化视图上创建约束,以确保{{1}物化视图中的1}}列总是1.这要求您创建一个适当的物化视图日志,这会在表上增加DML的开销。它还意味着在您提交之前不会违反约束,如果您的应用程序未编写为假定提交可能会失败,则可能会出现问题。

答案 1 :(得分:1)

考虑以不同的方式对关系进行建模,而不是添加约束。

由于课堂与课程之间存在一对一的关系。领导 我能看到实现所需结果的最简单方法是将领导者(class_teacher_id)与类记录一起存储。您需要向多对多表(class_teacher)添加一个唯一的代理键(class_teacher_id),然后您可以删除leader boolean列。

如果可以让一个没有领导者的班级,那么只需允许该学习者可以为空 当然不要忘记创建外键约束来强制class.leaderid和新的class_teacher.class_teacher_id之间的参照完整性。

答案 2 :(得分:1)

考虑将列is_Leader(布尔)列更改为leadership_rank(整数),在(Teacher, Class leadership_rank)上创建复合唯一约束。然后稍微改变语义,以便每个教师获得一个唯一的随机/递增/有意义的整数值。然后,所宣布的班级领导者是教师leadership_rank = 1(或者可能是小组的最低级别,以使事情变得更灵活),也许是使用视图。

答案 3 :(得分:1)

另一种方法是使用:

创建一个名为Leader的表
CREATE TABLE Leader
( Class
, Teacher
, PRIMARY KEY (Class)
, FOREIGN KEY (Class, Teacher)
    REFERENCES ClassTeacher (Class, Teacher)
) ;

并删除ClassTeacher.Leader列。

答案 4 :(得分:0)

要强制要求每个类都有一个领导者,您可以使用触发器

CREATE OR REPLACE TRIGGER tc
AFTER INSERT OR UPDATE OR DELETE
ON table_name
DECLARE
 v_res NUMBER;
BEGIN
  select count(*) 
  into v_res 
  from (
        select class from table_name
        minus
        select class from table_name where leader = 'Y'
        )
  ;

   if v_res > 0 
   then 
    raise_application_error(-20000, 'each class must have a leader'); 
   end if; 
END;
/