Constraints are used to maintain data integrity within relvars, ensuring that only valid data is stored. Constraints are defined at the schema level within a special relvar, known as the Constraint relvar, and each constraint consists of a name and a rule.
The rule is a boolean expression that is evaluated each time an assignment is made to a relvar - before the changes are committed (i.e. before they become visible to other users or operations). If the rule evaluates to true, the constraint is satisfied, and the assignment proceeds. If the rule evaluates to false (or if the evaluation fails), the entire assignment is rolled back and no changes are made.
Error Handling
Any failed constraints will be logged in the error relvar. After each assignment, users should check the error relvar to ensure no violations occurred. If errors are present, the user will need to handle them - either by retrying the assignment or applying some other form of remediation.
Types of Constraint
Here are some common types of constraints, with examples:
Key constraints
A key constraint ensures that every tuple in a given relvar is unique with respect to a specified set of attributes. For example:
key(S, S{SNO})
which expands to:
not given(S) or count(S) = count(S{SNO})
This rule ensures that the set of tuples in S remains unique with respect to the SNO attribute. If any tuple violates this uniqueness, the constraint fails, and the assignment is rolled back.
Foreign key constraints
A foreign key constraint ensures that every tuple in a given relation (the relation "left" of the ⊆ (subset) operator) has a matching tuple in another relation (the one "right" of the ⊆ operator, i.e. the "referenced" relation). The matching must occur with the same attribute(s) and data type(s). For example:
not given(SP, S) or SP{SNO} ⊆ S{SNO}
This rule can be interpreted as:
- First, the
not given(SP, S)check ensures that both theSPandSrelvars exist before applying the foreign key check. - The condition
SP{SNO} ⊆ S{SNO}ensures that the set ofSNOvalues from theSPrelvar is a subset of theSNOvalues from theSrelvar.
The not given check is needed in cases where the constraint might be added before the relvars themselves are created. It also allows for flexibility if either of the relvars is later dropped; the constraint would be ignored in such cases. This might not be what's needed. It would depend on the application, the initial data, and any future migration steps.
Note that a foreign key constraint restricts assignments to the relvars on both sides of the ⊆ operator: each tuple added to the left must have a matching entry in the right; and each tuple removed from the right must have no matching entries in the left.