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

发布于 2024-12-09 22:24:05 字数 406 浏览 0 评论 0原文

我有一个包含班级、教师和领导者行的表,

班级和教师是数字,领导者是布尔值(实际上只是一个 Char(1))

该表表示教师和班级之间的关系。

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

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

例如。

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

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

如果有人能提出如何将其表示为约束的想法,我将不胜感激。

I have a table with Class, Teacher, and Leader rows,

Class and Teacher are Numbers, and Leader is a Boolean (really just a Char(1))

The table represents a relationship between teachers and classes.

A class can have many teachers, or a teacher many classes.

I need to make a constraint or check so that for each distinct class, one, and only one of the rows it occurs in must have Leader as true.

Eg.

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

Would be accepted, as each distinct class, has one row in which it occurs having a Leader value of true, but no more than one row.

Would appreciate if anyone could offer up an idea on how to represent this as a constraint.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

江城子 2024-12-16 22:24:05

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

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

不幸的是,创建一个声明性约束来强制执行每个类都有一个领导者的要求并不容易。我知道执行此操作的唯一声明性方法是创建一个按类聚合数据的物化视图,将该物化视图设置为 REFRESH FAST 并在物化视图上创建一个约束,以确保物化视图中的 NUM_LEADERS 列始终为 1。这要求您创建适当的物化视图日志,这会增加表上 DML 的开销。这也意味着在您提交之前不会违反约束,如果您的应用程序没有编写为假设提交可能会失败,那么这可能会出现问题。

It's easy enough to create a function-based index that enforces the "no more than one leader" portion of the constraint

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

Unfortunately, it's not so easy to create a declarative constraint that enforces the requirement that each class has a leader. The only declarative way I'm aware of to do that would be to create a materialized view that aggregates the data by class, set that materialized view to REFRESH FAST and create a constraint on the materialized view that ensures that the NUM_LEADERS column in the materialized view is always 1. That requires that you create an appropriate materialized view log which adds overhead to DML on the table. It also means that the constraint won't be violated until you commit which can be problematic if your applications aren't written to assume that commit can ever fail.

回梦 2024-12-16 22:24:05

考虑将 is_Leader(布尔值)列更改为 leadership_rank(整数),对(教师、班级领导力_rank)创建复合唯一约束。然后稍微改变语义,以便每个老师得到一个唯一的随机/递增/有意义的整数值。然后,班级的宣布领导者是老师,其中leadership_rank = 1(或者可能是该组的最低排名,以使事情更加灵活),也许使用视图。

Consider changing the column is_Leader (Boolean) column to leadership_rank (Integer), create a compound unique constraint on (Teacher, Class leadership_rank). Then change the semantics slightly so that each teacher gets a unique random/incrementing/meaningful integer value. Then the declared leader for the class is the teacher where leadership_rank = 1 (or perhaps the lowest rank for the group, to make things a little more flexible), perhaps using a view.

无名指的心愿 2024-12-16 22:24:05

另一种方法是创建一个名为 Leader 的表,其中包含:

CREATE TABLE Leader
( Class
, Teacher
, PRIMARY KEY (Class)
, FOREIGN KEY (Class, Teacher)
    REFERENCES ClassTeacher (Class, Teacher)
) ;

并删除 ClassTeacher.Leader 列。

Another way would be to create a table, called Leader with:

CREATE TABLE Leader
( Class
, Teacher
, PRIMARY KEY (Class)
, FOREIGN KEY (Class, Teacher)
    REFERENCES ClassTeacher (Class, Teacher)
) ;

and drop the ClassTeacher.Leader column.

毁梦 2024-12-16 22:24:05

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

由于 class 和 class 之间存在一对一的关系。领导者
我认为实现您想要的结果的最简单方法是将领导者 (class_teacher_id) 与班级记录一起存储。您需要将唯一的代理键 (class_teacher_id) 添加到多对多表 (class_teacher),然后可以删除领导者布尔列。

如果可能有一个没有领导者的类,那么只需允许 learderid 可为空
当然,不要忘记创建外键约束以强制 class.leaderid 和新的 class_teacher.class_teacher_id 之间的引用完整性。

Rather than adding a constraint consider modeling the relationship in a different way.

As there is one-to-one relationship between class & leader
The easiest way I can see to achieve your desired results would be to store the leader (class_teacher_id) with the class record. You will need to add a unique surrogate key (class_teacher_id) to your many-to-many table (class_teacher), then you can drop the leader boolean column.

If it is possible to have a class without a leader then simply allow the learderid to be nullable
and of course don't forget create foreign key constraints to enforce referential integrity between the class.leaderid and the new class_teacher.class_teacher_id.

不奢求什么 2024-12-16 22:24:05

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

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;
/

To enforces the requirement that each class has a leader you can use a Trigger

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;
/
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文