CMPT 354 Database Systems I Chapter 7 Constraints and Triggers
Active Constraints Active Elements in SQL are statements that are executed on a given event. Constraints and triggers help specify integrity constraints. Why are they necessary? Make sure data entered is correct. Make sure data can be safely deleted. Separate tasks from DBMS programmers and application programmers. What types of constraints supported? Domain constraints. Primary keys, foreign keys and unique values. Attribute and tuple checks and schema assertion checks. Triggers.
Primary Keys Primary keys are declared inside a CREATE TABLE function using the keyword PRIMARY KEY in two possible ways: 1. Specify the keywords PRIMARY KEY after the attribute declaration. Cannot be used with multi-attribute key. 2. Specify the keywords PRIMARY KEY after all attribute declarations, followed by parenthesized attributes list. What are the benefits of declaring a primary key? Values cannot be NULL. Values must be unique. Column is probably automatically indexed. Table probably sorted on the key. Allows for easy referential integrity.
Primary Keys Example For the relation Students(SID:int, name:string, Address:string, Phone:int) CREATE TABLE Students (SID INT PRIMARY KEY, Name VARCHAR(50), Address VARCHAR(200), Phone INT); For the relation Courses(Course#:string, Section:string, ClassTime:string) CREATE TABLE Courses (Course# CHAR(8), Section CHAR(8), ClassTime VARCHAR(50), PRIMARY KEY (Course#, Section));
Uniqueness constraint Uniqueness constraint can be specified inside a CREATE TABLE function using the keywork UNIQUE just like PRIMARY KEY. NULLs are allowed in unique columns. Multiple NULL values can be declared (while only one Primary key). Why should we specify unique values? Candidate keys that are not primary keys. Values must be unique. Column is probably automatically indexed. How would a database system enforce a unique key constraint?
Foreign Keys Foreign keys can be specified in a CREATE TABLE function in similar ways to primary key, using the syntax: 1. Use the syntax REFERENCES <table>(<attr1>) after declaring an attribute. 2. Use the syntax: FOREIGN KEY (<attr_list>) REFERENCES <table>(<attr_list>) Foreign keys can only be declared on primary key or unique attributes in the reference table. Why? Foreign keys attributes in a record must exist in the reference table attributes. Why?
Foreign Keys Example Lets normalize the relation using BCNF: Students(SID, Name, Address, Phone, CourseID, Grade) Then we get the two relations: StudentInfo(SID:int, name:string, Address:string, Phone:int) Registered(SID:int, CourseID:string, Grade:float) Define the tables for students and registered. Can two normalized relations have the same primary keys? Can a foreign key be a primary key as well? Can two normalized relations have the same attribute as part of a primary key but not foreign key? SID appears both in StudentInfo and Registered. When is it a primary key, and when a foreign key? What is the primary key for registered?
Foreign Keys Example We can define the table for StudentInfo: CREATE TABLE StudentInfo (SID INT PRIMARY KEY, Name VARCHAR(50), Address VARCHAR(200), Phone INT UNIQUE); For Registered: CREATE TABLE Registered (SID INT REFERENCES StudentInfo(SID), CourseID CHAR(8), Grade FLOAT, PRIMARY KEY (SID, CourseID));
Foreign Keys Maintenance We have to decide what happens when we make a change that violates any constraints, here, foreign integrity constraints. For example: on the relations StudentInfo(SID:int, name:string, Address:string, Phone:int) Registered(SID:int, CourseID:string, Grade:float) what operations can violate foreign integrity? Delete, Insert, Update in Registered. Three possible outcomes depending on policy: SET DEFAULT: the operation is rejected (default). CASCADE: the changes are propagated through. SET NULL: the value is reset to NULL ON DELETE events or ON UPDATE events.
Referential Policy Example For the relation Registered: CREATE TABLE Registered (SID INT REFERENCES StudentInfo(SID) ON DELETE CASCADE ON UPDATE CASCADE, CourseID CHAR(8), Grade FLOAT, PRIMARY KEY (SID, CourseID)); What happens when a student is deleted from StudentInfo? What happens when a student SID is corrected in StudentInfo? What if SID is changed in Registered?
Deferring Evaluation Sometime it is preferable to have constraints checked only at the end of a transaction. When? Circular Reference or want to add tuples in any order. Example: For the relations StudentInfo and Registered: StudentInfo(SID, name, Address, Phone, StudyTime) Registered(SID:int, CourseID:string, Time, Grade:float) Registerd.SID is determined by StudentInfo.SID and StudyTime is determined by any course time. Can declare attributes DEFERABLE or NOT DEFERABLE. Can have INITIALLY DEFERRED or INITIALLY IMMEDIATE initial values. Can set deferred status using SET CONSTRAINT <ConstraintName> DEFERRED or IMMEDIATE.
Deferring Checks Example We can define the tables for StudentInfo and Registered: CREATE TABLE StudentInfo (SID INT PRIMARY KEY, Name VARCHAR(50), Address VARCHAR(200), Phone INT UNIQUE, StudyTime TIME REFERENCES Registered(CourseTime) DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Registered (SID INT REFERENCES StudentInfo(SID) ON DELETE CASCADE ON UPDATE CASCADE, CourseID CHAR(8), Grade FLOAT, CourseTime TIME UNIQUE, PRIMARY KEY (SID, CourseID));
Other Attribute Values Can restrict an attribute from taking NULL values using the keyword NOT NULL after the attribute declaration. Can given an attribute default values by using the keyword DEFAULT with a value after the attribute declaration. For example: CREATE TABLE StudentInfo (SID INT PRIMARY KEY, Name VARCHAR(50) NOT NULL, Address VARCHAR(200) DEFAULT SFU, Phone INT UNIQUE, StudyTime TIME REFERENCES Registered(CourseTime) DEFERRABLE INITIALLY DEFERRED));
Check Constraints A check constraint verifies that a certain SQL expression is true. Why is it necessary? Two types of check constraints can be defined inside a CREATE TABLE clause Attribute check: Evaluated whenever an attribute value changes or is assigned. Tuple check: Evaluated whenever a tuple changes or is added. If the check is violated the modification is rejected. The check clause is specified as CHECK followed by a any SQL expression in brackets. Which expressions allowed? Can be defined after an attribute for attribute check or after all attributes for a tuple check.
Check Constraints Example For example take the relation: Accounts(SSN:int, Account#:int, balance: real, joindate:date) How would we create the table our overdraft limit was specified to be -$500? CREATE TABLE Accounts (SSN INT REFERENCES Clients(SSN) NOT DEFERABLE NOT NULL, Account# INT PRIMARY KEY, Balance REAL DEFAULT 0 CHECK (Balance > -500), JoinDate DATE DEFAULT DATE now ); When is balance checked? Does the check always work?
Check Constraints Example For the relation: Accounts(SSN:int, Account#:int, balance: real, joindate:date) In addition to setting our overdraft limit to -$500 we also want to verify that the JoinDate is not a future date. CREATE TABLE Accounts (SSN INT REFERENCES Clients(SSN) NOT DEFERABLE NOT NULL, Account# INT PRIMARY KEY, Balance REAL DEFAULT 0, JoinDate DATE DEFAULT DATE now, CHECK (Balance > -500 AND JoinDate <= DATE now )); When is the Check being performed? Is it possible to have it as two attribute checks? What if instead of AND there was OR?
Named Constraints Any constraint can be named at definition by appending CONSTRAINT <Constraint_Name> before the definition. Example: CONSTRAINT OverdraftLimit CHECK (Balance > -500) Can add and drop constraints in ALTER TABLE using the ADD CONSTRAINT and DROP CONSTRAINT keywords. The constraint name must be specified after DROP CONSTRAINT but is optional for ADD CONSTRAINT. Example: ALTER TABLE Accounts DROP CONSTRAINT OverdraftLimit;
Assertions An assertion is a Boolean SQL Check constraint that must always be true. Database changes violating an assertion are rejected. Assertions are schema level. Define an Assertion by the syntax: CREATE ASSERTION <name> CHECK (<expression>) When are assertions necessary? For the students, registered, and courses relations, create a table registered that verifies that every students is taking at least 3 courses with tuple or attribute level Checks. What happens if a course is cancelled due to low registration? Assertions execute when any underlying relations change Time consuming in a database!
Assertions Example For the relations: Students(SID:int, name:string, Address:string, Phone:int) Courses(Course#:string, Section:string, ClassTime:string) Registered(SID:int, CourseID:string, Grade:float) Enforce an assertion on registered to have at least 3 courses for each student: CREATE ASSERTION EnoughCourses CHECK (3 <= ALL (SELECT Count(CourseID) FROM Registered INNER JOIN Courses ON Registered.CourseID = Courses.Course# GROUP BY Registered.SID) ); When is this assertion executed? What if all course sections have been deleted?
Triggers Triggers offer a more powerful active elements in SQL. Triggers are executed only on specified events. A trigger can be executed conditionally. A trigger also specifies the action to take if its condition is true using a WHEN clause. The syntax for a trigger starts with CREATE TIGGER <name>. Then the event is AFTER or BEFORE a trigger event UPDATE, INSERT, or DELETE, ON <table>. UPDATE can be specialized with OF <attr>. Can reference old and new values using REFERENCING OLD ROW AS <name>, NEW ROW AS <name> FOR EACH ROW, or OLD TABLE and NEW TABLE FOR EACH STATEMENT.
Triggers Example For the relations: Workforce(SIN:int, Name:string) Hire(InterviewerSIN:int, HireeSIN:int) WorkIn(WorkerSIN:int, DeptName:string) We want to make sure that only people working in HR can hire workers: CREATE TRIGGER HRHiringConstraint AFTER INSERT ON Workforce REFERENCING NEW ROW AS nrow FOR EACH ROW WHEN NOT EXISTS (SELECT * FROM Hire JOIN WorkIn ON InterviewerSIN = WorkerSIN WHERE HireeSIN = nrow.sin AND DeptName = H-R ) DELETE FROM Workforce WHERE SIN = nrow.sin