我有一个包含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,但不超过一行。
如果有人能提出如何将此作为约束来表达的想法,我将不胜感激。
答案 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;
/