Integrity constraints impose restrictions on the allowable data in the database, in addition to the simple structure and type restrictions imposed by the basic schema definition.
Question: We've already seen a few kinds of integrity constraints. What are they?
1. 2. 3.
Why use integrity constraints?
Example schema:
Student(ID, name, address, GPA, sizeHS) Campus(location, enrollment, rank) Apply(ID, location, date, major, decision)Example constraints:
Apply.ID and Apply.location appear in
Student.ID and Campus.location, respectively
Campus.rank <= 10
Student(ID, name, GPA, sizeHS) Campus(location, enrollment, rank) Apply(ID, location, major, decision)Covered:
Constraints on values for Relation.Attribute
CHECK(<condition>)" to attribute.
<condition> is like a SQL Where clause, can refer to
attribute itself.
CREATE TABLE Student (...
GPA float CHECK(GPA <= 4.0 AND GPA > 0),
...)
CREATE TABLE Apply (...
decision char CHECK(decision in ('Y','N','U'))
...)
Conditions can be more complex, e.g., with subqueries.
Apply (...
major char(10) CHECK(major NOT IN
(SELECT dept-name FROM Dept
WHERE status = 'full'))
...)
Question: Can we encode referential integrity constraints this way?
-> Attribute-based constraints are only checked on inserts and updates to that relation, NOT on modifications to relations referenced in subqueries -- significant "hole" in constraint-checking.
Relation.Tuple
Similar to attribute-based constraints except CHECK
applies to entire tuples.
=> Specified separately in table definition
Example:
CREATE TABLE Campus(location char(25),
enrollment integer,
rank integer,
CHECK(enrollment >= 10,000 OR rank > 5)
(Example encodes enrollment < 10,000 => rank > 5)
As with attribute-based constraints, can have subqueries but constraint is only checked when the relation itself is modified
In SQL, stand-alone statement:
CREATE ASSERTION <name> CHECK(<condition>)Example: Average GPA is > 3.0 and average sizeHS is < 1000
CREATE ASSERTION Avgs CHECK(
3.0 < (SELECT avg(GPA) FROM Student) AND
1000 > (SELECT avg(sizeHS) FROM Student))
Example: A student with GPA < 3.0 can only apply to campuses with rank > 4.
CREATE ASSERTION RestrictApps CHECK(
NOT EXISTS (SELECT * FROM Student, Apply, Campus
WHERE Student.ID = Apply.ID
AND Apply.location = Campus.location
AND Student.GPA < 3.0 AND Campus.rank <= 4))
Assertions checked for each modification that could potentially
violate them.
Question: What operations could violate assertion Avgs?
Question: What operations could violate assertion RestrictApps?
Question: Can we encode referential integrity constraints this way?
General form (SQL3):
CREATE TRIGGER <name> BEFORE | AFTER | INSTEAD OF <events> <referencing clause> // optional FOR EACH ROW // optional WHEN (<condition>) // optional <action><events> can be:
INSERT ON R DELETE ON R UPDATE [OF A1, A2, ..., An] ON R
AFTER <events> are the most common and useful.
FOR EACH ROW
REFERENCING <thing1>
AS <var1> <thing2> AS <var2>, etc.
OLD TABLE - previous values of deleted or updated tuples,
row-level or statement-level,
DELETE or UPDATE
NEW TABLE - current values of inserted or updated tuples,
row-level or statement-level,
INSERT or UPDATE
OLD ROW - previous value of deleted or updated tuple,
row-level only,
DELETE or UPDATE
NEW ROW - current value of inserted or updated tuple,
row-level only,
INSERT or UPDATE
If an application tuple is inserted for a student with
GPA > 3.9 and sizeHS > 1500 to Berkeley, set decision
to "Y".
CREATE TRIGGER AutoAccept
AFTER INSERT ON Apply
REFERENCING NEW ROW AS NewApp
FOR EACH ROW
WHEN (NewApp.location = 'Berkeley' AND
3.9 < (SELECT GPA FROM Student WHERE ID = NewApp.ID) AND
1500 < (SELECT sizeHS FROM Student WHERE ID = NewApp.ID))
UPDATE Apply
SET decision = 'Y'
WHERE ID = NewApp.ID
AND location = NewApp.location
AND date = NewApp.date
Same trigger but no WHEN condition
CREATE TRIGGER AutoAccept
AFTER INSERT ON Apply
REFERENCING NEW ROW AS NewApp
FOR EACH ROW
UPDATE Apply
SET decision = 'Y'
WHERE ID = NewApp.ID
AND location = NewApp.location
AND date = NewApp.date
AND location = 'Berkeley'
AND 3.9 < (SELECT GPA FROM Student WHERE ID = Apply.ID)
AND 1500 < (SELECT sizeHS FROM Student WHERE ID = Apply.ID)
Same trigger but statement-level
CREATE TRIGGER AutoAccept
AFTER INSERT ON Apply
REFERENCING NEW TABLE AS NewApps
UPDATE Apply
SET decision = 'Y'
WHERE (ID,location,date) IN (SELECT ID,location,date FROM NewApps)
AND location = 'Berkeley'
AND 3.9 < (SELECT GPA FROM Student WHERE ID = Apply.ID)
AND 1500 < (SELECT sizeHS FROM Student WHERE ID = Apply.ID)
If campus enrollment increases from below 7,000 to above
7,000, delete all applications to that campus dated after 2/15/08 and
set all "Y" decisions for applications before 2/15/08 to
"U".
CREATE TRIGGER TooMany
AFTER UPDATE OF enrollment ON Campus
REFERENCING OLD ROW AS OldVal NEW ROW AS NewVal
FOR EACH ROW
WHEN (OldVal.enrollment <= 7,000 AND NewVal.enrollment > 7,000)
DELETE FROM Apply
WHERE location = NewVal.location AND date > 2/15/08;
UPDATE Apply
SET decision = 'U'
WHERE location = NewVal.location
AND decision = 'Y'
Triggers and assertions
OLD TABLE and NEW TABLE
Student(ID, name, GPA, sizeHS) Campus(location, enrollment, rank) Apply(ID, location, major, decision)Concepts covered: