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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With