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
CREATE TABLE Student (ID integer NOT NULL, name char(30) NOT NULL, address char(100), GPA float NOT NULL, sizeHS integer)
ID
is key for Student
=>Student
can have the same
value for their ID
attribute
There are two kinds of keys in SQL:
PRIMARY KEY
: at most one per table, automatically
non-null, automatically indexed (in Oracle)
UNIQUE
: any number per table, automatically indexed
(in Oracle)
CREATE TABLE Student (ID integer PRIMARY KEY, name char(30), address char(100), GPA float, sizeHS integer, UNIQUE (name,address))
ID
appears in Apply
then it also appears in Student
.
location
appears in Apply
then it also appears in Campus
.
Question: Does the reverse direction in these examples make sense?
Terminology:
Apply.ID
"references" Student.ID
PRIMARY KEY
or UNIQUE
(e.g., Student.ID
, Student.(name,address)
, Campus.location
)
FOREIGN KEY
(e.g., Apply.ID
, Apply.location
)
CREATE TABLE Apply(ID integer REFERENCES Student(ID), location char(25), date char(10), major char(10), decision char, FOREIGN KEY (location) REFERENCES Campus(location))Can omit referenced attribute name if it's the same as referencing attribute:
ID integer REFERENCES Student, ...Can have multi-attribute referential integrity.
Can have referential integrity within a single table.
Example:
Dorm(first-name, last-name, room-number, phone-number, roommate-first-name, roommate-last-name, PRIMARY KEY (first-name,last-name), FOREIGN KEY (roommate-first-name,roommate-last-name) REFERENCES Dorm(first-name,last-name))
R(P, ...)
and S(..., F references R(P), ...)
Question: What modification operations can violate constraint?
1. 2. 3. 4.Inserts/updates to S that violate constraint are disallowed.
(figure)
Four options:
SET NULL
- set all referencing values to NULL
SET DEFAULT
- set all referencing values to default
for that column (error if default value not in R.P)
CASCADE
- delete all tuples with referencing values
CASCADE
mirrors update)
See textbook for syntax.
Question: Why is referenced attribute required to be PRIMARY KEY
or UNIQUE?
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
?
Q: Can we encode referential integrity constraints this way?
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. Don't
worry too much about BEFORE
and INSTEAD OF
, they can
be messy.
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
Example: 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.dateQuestion: Can we achieve the same effect using assertions?
Example: Same trigger without
FOR EACH ROW
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)Example: If campus enrollment increases from below 7,000 to above 7,000, delete all applications to that campus dated after 2/15/05 and set all "
Y
" decisions for applications before 2/15/05 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/05; UPDATE Apply SET decision = 'U' WHERE location = NewVal.location AND decision = 'Y'Question: Can we achieve the same effect using assertions?
Triggers and assertions:
ON DELETE SET NULL
" and "ON DELETE CASCADE
"
CHECK
constraints
without subqueries
INSTEAD OF
for triggers on views only (don't try this at home)
OLD TABLE
or NEW TABLE
in REFERENCING
clause
OLD
instead of OLD ROW
and NEW
instead
of NEW ROW
WHEN
clause allowed only with FOR EACH ROW
WHEN
condition
Question: What is being prevented by restricting triggering interactions?