### integrity-constraints

```IC and Triggers in SQL
HAVING Clause
Find age of the youngest sailor
with age <=18, for each rating
with at least 2 such sailors
SELECT S.rating, MIN (S.age) AS minage
FROM Sailors S
WHERE S.age >= 18
GROUP BY S.rating
HAVING COUNT (*) > 1
rating
3
7
8
minage
25.5
35.0
25.5
Sailors instance:
sid
22
29
31
32
58
64
71
74
85
95
96
sname rating age
dustin
7 45.0
brutus
1 33.0
lubber
8 55.5
andy
8 25.5
rusty
10 35.0
horatio
7 35.0
zorba
10 16.0
horatio
9 35.0
art
3 25.5
bob
3 63.5
frodo
3 25.5
Integrity Constraints (Review)
• An IC describes conditions that every legal
instance of a relation must satisfy
violate IC’s
• Types of IC’s: Domain constraints, primary key
constraints, foreign key constraints, non-null,
general constraints
An Example via CHECK Clause
CREATE TABLE Stu (
sid INTEGER,
sname CHAR(10),
rating INTEGER,
age REAL,
PRIMARY KEY (sid),
CHECK (rating >= 1 AND rating <= 10 )
)
CHECK Example
CREATE TABLE Stu (
sid INTEGER,
sname CHAR(10),
rating INTEGER,
age REAL,
PRIMARY KEY (sid),
CONSTRAINT checkRating
CHECK (rating >= 1 AND rating <= 10 )
)
ASSERTION Example
Constraints Over Multiple Relations
•
•
•
Consider a very small school: the count of students and professors should be less than 500
The following is a poor integrity test as it is associated with one relation (the Stu table could
be empty and thus the integrity rule is never checked!
Disassociate from the Stu table
CREATE TABLE Stu (
sid INTEGER,
sname CHAR(10),
rating INTEGER,
age REAL,
PRIMARY KEY (sid),
CHECK (
(SELECT COUNT (S.sid) FROM Stu S) +
(SELECT COUNT (P.pid) FROM Prof P) < 500 )
)
ASSERTION Example
Constraints Over Multiple Relations
CREATE ASSERTION smallSchool
CHECK (
(SELECT COUNT (S.sid) FROM Stu S) +
(SELECT COUNT (P.pid) FROM Prof P) < 500
)
ASSERTION Example
The KEY Constraint
CREATE ASSERTION Key
CHECK (
(SELECT COUNT (DISTINCT sid) FROM Stu) =
(SELECT COUNT (*) FROM Stu)
);
• Note: ASSERTION is in standard SQL but not
implemented
Triggers
• Event-Condition-Action rules: procedures that start
automatically if a change occurs to the DBMS
When event occurs, check condition; if true do action
• Why: to move monitoring logic from applications into the DBMS
(more modular, consistency among applications, no
duplications)
• Allow automatic repair
• Database stores triggers just as regular data so they are
persistent and accessible to all database operations
• Useful for security purposes
• Triggers make a passive database “active”
• To move application logic and business rules
into database
• Allows more functionality for DBAs to
establish vital constraints/rules of applications
• Rules managed in some central “place”
• Rules automatically enforced by DBMS, no
matter which applications later come on line
The Event-Condition-Action Model
• Actions may apply before or after the
triggering event is executed
• An SQL statement may change several rows
– Apply action once per SQL statement
– Apply action for each row changed by SQL
statement
The Company Database
EMPLOYEE(Name, SSN, Salary, DNO, SupervisorSSN, JobCode)
STARTING_PAY(JobCode, StartPay)
1. Limit all salary increases to 50%.
2. Enforce policy that salaries may never decrease.
3. Maintain TotalSalary in DEPARTMENT relation as
employees and their salaries change. (EN, Fig. 23.2 (a))
4. Inform a supervisor whenever a supervisee’s salary
becomes larger than the supervisor’s. (EN, Fig. 23.2 (b))
5. All new hires for a given job code get the same starting
salary, which is available in the STARTING_PAY table.
Limit all salary increases to 50%
create trigger emp_salary_limit
before update of EMPLOYEE
for each row
when (new.Salary > 1.5 * old.Salary)
set new.Salary = 1.5 * old.Salary;
“new” refers to
the new tuple.
“old” refers to
the old tuple.
Enforce policy that salaries may never decrease
create trigger emp_salary_no_decrease
before update of EMPLOYEE
for each row
Method depends on
when (new.Salary < old.Salary)
DBMS.
begin
log the event;
signal error condition;
end
All new hires for a given job code get the same
starting salary
EMPLOYEE(Name, SSN, Salary, DNO, SupervisorSSN, JobCode)
STARTING_PAY(JobCode, StartPay)
create trigger emp_start_pay
before insert on EMPLOYEE
for each row
set Salary =
(select StartPay
from
STARTING_PAY
where JobCode = new.JobCode)
Trigger Syntax
CREATE [OR REPLACE ] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF }
{INSERT [OR] | UPDATE [OR] | DELETE}
[OF col_name]
ON table_name
[REFERENCING OLD AS o NEW AS n]
[FOR EACH ROW]
WHEN (condition)
BEGIN
--- sql statements
END;
```