SELECT deptno FROM Emps WHERE sal > 3000

Theory, Practice & Methodology
of Relational Database
Design and Programming
Copyright © Ellis Cohen 2002-2008
Relational
State
Assertions
These slides are licensed under a Creative Commons
Attribution-NonCommercial-ShareAlike 2.5 License.
For more information on how you may use them,
please see http://www.openlineconsult.com/db
1
Overview of Lecture
Relational State Assertions
Assertions with EXISTS
Comparing Vector Relations
and Scalar Values
Comparing Relations
Uniqueness Assertions
© Ellis Cohen 2001-2008
2
Relational
State Assertions
© Ellis Cohen 2001-2008
3
Relational Mapping
Conceptual Model
Conceptual ER Model
(e.g. UML/Crow Magnum)
Conceptual
State Constraints
(refers to ER Model)
Relational Schema
Relational
State Constraints
(refers to Relational
Schema)
Relational Model
© Ellis Cohen 2001-2008
4
Relational State Constraints
Check Constraints (CHECK, NOT NULL)
Ensures that each tuple in a table satisfies a
condition
Uniqueness Constraints (UNIQUE, PRIMARY KEY)
Ensures that all values in a column are unique
Foreign Key Constraints (REFERENCES)
Ensures that a value in one column (or group of
columns) matches a value in a referenced unique
column (or group of columns)
Relational State Assertions (ASSERTION)
Specifies an arbitrary condition (possibly involving
multiple tables) that should remain satisfied
© Ellis Cohen 2001-2008
5
Relational State Assertions in SQL
A relational state assertion is a kind
of relational state constraint
expressed as an arbitrary querybased boolean condition applied to
the relational model
Example:
Corresponding
Relational
State
Assertion:
Conceptual State Constraint
There are at least 5 clerks
in department 10
(SELECT count(*) FROM Emps
WHERE job = 'CLERK'
AND deptno = 10) >= 5
© Ellis Cohen 2001-2008
6
CREATE ASSERTION
CREATE ASSERTION assertion-name
CHECK( boolean-expr )
CREATE ASSERTION LotsOfClerks
CHECK(
(SELECT count(*) FROM Emps
WHERE job = 'CLERK'
AND deptno = 10) >= 5)
is part of the SQL-92 standard, but is
not currently supported by
commercial databases.
So, we will have to find other ways to
enforce state assertions
© Ellis Cohen 2001-2008
7
Enforcing State Assertions
There are two ways to enforce state
assertions that can't be directly
supported in SQL
• Database Enforcement:
Use triggers (in the data-tier) to enforce
assertions
• Application Enforcement:
Enforce assertions through code
implemented in
• user operations (in the middle-tier) or
• stored DB operations (in the data-tier)
© Ellis Cohen 2001-2008
8
Writing Assertions
Even though most databases do not support
CREATE ASSERTION, it is still useful to
write state assertions for conceptual
state constraints that can't be
implemented using built-in SQL
constraints.
Why write state assertions?
• To take ambiguously stated conceptual
constraints and generate something clear
and unambiguous (though harder to
read)
• To take a step that will ultimately make it
easier to code the constraint's
implementation.
© Ellis Cohen 2001-2008
9
SQL with State Assertions
CREATE TABLE Depts(
deptno number(3) primary key,
dname varchar(20) not null )
CREATE TABLE Emps(
empno number(4) primary key,
ename varchar(30) not null,
street
varchar(40),
city
varchar(20),
state
char(2) check (state <> 'CA'),
zip
char(5),
deptno number(3) references Depts,
mgr
number(4) references Emps,
check (empno <> mgr) )
CREATE ASSERTION OneBiggie CHECK(
(SELECT count(*) FROM Emps WHERE sal > 4500)
=1)
What does it mean?
© Ellis Cohen 2001-2008
10
OneBiggie
OneBiggie:
(SELECT count(*)
FROM Emps
WHERE sal > 4500) = 1
There is exactly one employee
who makes more than 4500
© Ellis Cohen 2001-2008
11
SQL Value Coercion
(SELECT count(*) FROM Emps
WHERE deptno = 10 AND job = 'CLERK') ≥ 5
(SELECT count(*) FROM Emps
WHERE deptno = 10 AND job = 'CLERK')
is actually a scalar result set (a.k.a. a scalar relation):
a relation with a single attribute and a single tuple
8
How can we compare the relation to 5?
8
≥5
SQL automatically coerces scalar relations to values
when necessary
8≥5
© Ellis Cohen 2001-2008
12
A Distinct Count Problem
What's the meaning of
(SELECT count(DISTINCT deptno)
FROM Emps
WHERE job = 'SALESMAN') < 3
© Ellis Cohen 2001-2008
13
SQL Assertion Answer
No more than 2 departments
have salesmen
(SELECT count(DISTINCT deptno)
FROM Emps
WHERE job = 'SALESMAN') < 3
Note that this does NOT indicate the number of salesman,
just the # of depts that have (1 or more) salesmen
© Ellis Cohen 2001-2008
14
Comparing Counts
Depts( deptno, dname, loc )
Emps( empno, ename, street, city,
state, zip, deptno, mgr )
• check( empno <> mgr)
• deptno references Depts
DeptEmps:
(SELECT count(DISTINCT deptno)
FROM Emps) >=
(SELECT count(*) FROM Depts)
What does DeptEmps mean?
© Ellis Cohen 2001-2008
15
Mandatory Parent Participation
(SELECT count(DISTINCT deptno)
FROM Emps) >=
(SELECT count(*) FROM Depts)
The # of depts with employees >=
the # of depts
(Assuming referential integrity ensures that
every employee department is in Depts)
 Every department has at least one
employee
works for
Dept
Employee
deptno
dname
empno
ename
addr
© Ellis Cohen 2001-2008
16
Assertions
with
EXISTS
© Ellis Cohen 2001-2008
17
Existence Problem
Consider the constraint
There is at least one employee
whose (weekly) salary is more
than $4000
What's the corresponding assertion?
© Ellis Cohen 2001-2008
18
Existence Solution
There is at least one employee whose
(weekly) salary is more than $4000
(SELECT count(*) FROM Emps
WHERE sal > 4000) > 0
© Ellis Cohen 2001-2008
19
Using EXISTS
The company has at least one analyst
(SELECT count(*) FROM Emps
WHERE job = 'ANALYST') > 0
can also be written using the built-in
SQL function EXISTS
EXISTS( SELECT * FROM Emps
WHERE job = 'ANALYST' )
which is true if evaluation of the
SELECT results in at least one tuple
© Ellis Cohen 2001-2008
20
Using NOT EXISTS
The company has no peons
(SELECT count(*) FROM Emps
WHERE job = 'PEON') = 0
can also be written using NOT along
with the EXISTS function
NOT EXISTS( SELECT * FROM Emps
WHERE job = 'PEON' )
which is true if evaluation of the
SELECT results in zero tuples
© Ellis Cohen 2001-2008
21
NOT EXISTS & CHECK
NOT EXISTS used with a simple SELECT
can be checked a tuple at a time 
It corresponds to a CHECK constraint!
NOT EXISTS( SELECT * FROM Emps
WHERE job = 'PEON' )
CHECK( job != 'PEON )
© Ellis Cohen 2001-2008
22
Simple NOT EXISTS Problem
Consider the assertion
NOT EXISTS( SELECT * FROM Emps
WHERE job = 'DEPTMGR'
AND sal < 1500 )
Rewrite this as a CHECK constraint
© Ellis Cohen 2001-2008
23
Simple NOT EXISTS Solution
NOT EXISTS( SELECT * FROM Emps
WHERE job = 'DEPTMGR'
AND sal < 1500 )
CHECK( job != 'DEPTMGR'
OR sal >= 1500 )
© Ellis Cohen 2001-2008
24
Complex NOT EXISTS
NOT EXISTS(
SELECT deptno FROM Emps
WHERE job = 'DEPTMGR'
GROUP BY deptno
HAVING count(*) > 1 )
What does this mean?
Can it be turned into a CHECK constraint?
© Ellis Cohen 2001-2008
25
Complex NOT EXISTS Solution
NOT EXISTS(
SELECT deptno FROM Emps
WHERE job = 'DEPTMGR'
GROUP BY deptno
HAVING count(*) > 1 )
No dept has more than
1 dept manager
Cannot be expressed
as a CHECK constraint
© Ellis Cohen 2001-2008
26
Comparing
Vector Relations &
Scalar Values
© Ellis Cohen 2001-2008
27
Assertion Question
Suppose we want to assert that
Every dept manager makes 1500 or more
(assuming every employee has a job & sal)
Can we write
(SELECT sal FROM Emps
WHERE job = 'DEPTMGR') >= 1500
© Ellis Cohen 2001-2008
28
Cannot Coerce Vector Relations
SELECT sal FROM Emps
WHERE job = 'DEPTMGR'
sal
2975
2850
2450
This is a vector relation:
a relation with a single
attribute and
possibly multiple rows
sal
2975
2850
2450
≥ 1500
Can't compare or coerce vector relations to values
© Ellis Cohen 2001-2008
29
Comparing Vectors to Values
In comparing a vector relation to a scalar,
there are (at least) two reasonable
comparisons you might want to make
sal
2975
2850
2450
? ≥ 1500
1. Are all of the sal values 1500 or more
2. Is there any sal value that is 1500 or more
Rather than choosing one of these as the meaning of ≥
we augment the comparison to explicitly specify one of them
© Ellis Cohen 2001-2008
30
ALL Comparisons
sal
2975
2850
2450
Are all of the salaries
≥ 1500?
(SELECT sal FROM Emps WHERE job = 'DEPTMGR') ALL >= 1500
– NOT STANDARD SQL,
but we'll use it informally when writing assertions
1500 <= ALL (SELECT sal FROM Emps WHERE job = 'DEPTMGR')
– STANDARD SQL !
How else could this be written in SQL?
© Ellis Cohen 2001-2008
31
ALL SQL Alternatives
(SELECT sal FROM Emps WHERE job = 'DEPTMGR')
ALL >= 1500
All deptmgr salaries ≥ 1500
1500 <= ALL (SELECT sal FROM Emps WHERE job =
'DEPTMGR')
NOT EXISTS( SELECT * FROM Emps
WHERE job = 'DEPTMGR' AND sal < 1500 )
(SELECT min(sal) FROM Emps
WHERE job = 'DEPTMGR') ≥ 1500
© Ellis Cohen 2001-2008
32
ANY Comparisons
sal
2975
2850
2450
Are any of the salaries
≥ 1500?
(SELECT sal FROM Emps WHERE job = 'DEPTMGR') ANY >= 1500
– NOT STANDARD SQL,
but we'll use it informally when writing assertions
1500 <= ANY (SELECT sal FROM Emps WHERE job = 'DEPTMGR')
– STANDARD SQL !
How else could this be written in SQL?
© Ellis Cohen 2001-2008
33
ANY SQL Alternatives
(SELECT sal FROM Emps WHERE job = 'DEPTMGR')
ANY >= 1500
There are some deptmgr salaries ≥ 1500
1500 <= ANY (SELECT sal FROM Emps WHERE job =
'DEPTMGR')
EXISTS( SELECT * FROM Emps
WHERE job = 'DEPTMGR' AND sal >= 1500 )
(SELECT max(sal) FROM Emps
WHERE job = 'DEPTMGR') ≥ 1500
© Ellis Cohen 2001-2008
34
Vector Comparison Problems
What's the meaning of
(SELECT count(*) FROM Emps
WHERE sal > 3000
GROUP BY deptno) ALL <= 1
(SELECT count(DISTINCT job)
FROM Emps
GROUP BY deptno) ALL <= 5
© Ellis Cohen 2001-2008
35
Vector Comparison Answer
(SELECT count(*) FROM Emps
WHERE sal > 3000
GROUP BY deptno) ALL <= 1
No department has more than 1 employee
who makes > 3000
(Some depts might not have any such employee)
(SELECT count(DISTINCT job)
FROM Emps
GROUP BY deptno) ALL <= 5
No department has more than 5 different
kinds of jobs
© Ellis Cohen 2001-2008
36
Comparing
Relations
© Ellis Cohen 2001-2008
37
Mandatory Parent Participation
Question
Emps
empno ename
addr deptno
Depts
7499
ALLEN
...
30
deptno
7654
MARTIN
…
30
30
SALES
7698
BLAKE
…
30
7839
KING
…
10
10
ACCOUNTING
7844
TURNER
…
30
50
SUPPORT
7986
STERN
…
10
dname
Does every department have an employee?
© Ellis Cohen 2001-2008
38
Mandatory Parent Participation
Testing
Emps
empno ename
Depts
addr deptno
7499
ALLEN
...
30
deptno
7654
MARTIN
…
30
30
SALES
7698
BLAKE
…
30
7839
KING
…
10
10
ACCOUNTING
7844
TURNER
…
30
50
SUPPORT
7986
STERN
…
10
Departments
that have employees
SELECT DISTINCT deptno
FROM Emps
Known Departments
SELECT deptno
FROM Depts
deptno
30
10
dname
deptno
≠
30
10
50
© Ellis Cohen 2001-2008
39
Relation Equality
R1 = R2
NOT Standard SQL, but commonly used
informally for writing relational assertions
Two relationships are equal if
• They have the same attribute names
(which are unordered)
• They have identical collections of
tuples (which are unordered)
• If R1 has duplicate copies of a tuple,
then R2 has the same number of
copies of the same tuple (and vice
versa)
© Ellis Cohen 2001-2008
40
Specifying
Mandatory Parent Participation
Dept
employs
Employee
(SELECT DISTINCT deptno FROM Emps)
= (SELECT deptno FROM Depts)
Dept
employs
Employee
(SELECT DISTINCT deptno FROM Emps
WHERE deptno IS NOT NULL)
= (SELECT deptno FROM Depts)
© Ellis Cohen 2001-2008
41
Cardinality Constraints
Dept
employs
2..5
Employee
(SELECT deptno FROM Emps
WHERE deptno IS NOT NULL
GROUP BY deptno
HAVING count(*) BETWEEN 2 AND 5)
= (SELECT deptno FROM Depts)
© Ellis Cohen 2001-2008
42
Relation Comparisons
R1  R2 (or equivalently R2  R1)
They have the same attribute names, and
every tuple that is in R1 is also in R2
(including at least as many copies of each duplicate)
[OK to type this as R1 <= R2]
R1 = R2
(R1  R2) and (R2  R1)
R1 and R2 have the same tuples
(and the number of duplicates match)
R1 != R2
not (R1 = R2)
R1  R2 (or equivalently R2  R1)
(R1  R2) and (R1 != R2)
[can type R1 < R2]
The Relation Comparison Operators
are NOT part of standard SQL
© Ellis Cohen 2001-2008
43
State Assertion Exercise
Assuming that every employee
is assigned to a department,
What's the meaning of this state assertions?
(SELECT DISTINCT depnto FROM Emps) 
(SELECT deptno FROM Depts)
© Ellis Cohen 2001-2008
44
State Assertion Answer
Emps
empno
ename
addr
deptno
7499
ALLEN
...
30
7654
MARTIN
…
30
7844
TURNER
…
30
7212
LAVICH
…
7698
BLAKE
7986
STERN
Depts
deptno
dname
30
SALES
30
10
ACCOUNTING
…
10
50
SUPPORT
…
10
30
30

10
10
50
SELECT DISTINCT depnto
FROM Emps
SELECT deptno FROM Depts
Every dept # in Emps (assuming no nulls) is also included in Depts
© Ellis Cohen 2001-2008
45
Referential Integrity Constraints
Foreign Key Constraint
(SELECT DISTINCT depnto FROM Emps
WHERE deptno IS NOT NULL)
 (SELECT deptno FROM Depts)
Referential Integrity Constraint
(SELECT DISTINCT hiredate FROM Emps
WHERE hiredate IS NOT NULL)
 (SELECT DISTINCT startdate FROM Projs)
© Ellis Cohen 2001-2008
46
Comparing Assertions
Assuming that every employee
is assigned to a department,
What's the difference between these
two state assertions?
(SELECT deptno FROM Depts) =
(SELECT DISTINCT depnto FROM Emps
WHERE job = 'CLERK')
(SELECT deptno FROM Depts) 
(SELECT depnto FROM Emps
WHERE job = 'CLERK')
© Ellis Cohen 2001-2008
47
Answer Comparing Assertions
Every department has a clerk
(Assuming every employee in Emps
is assigned to a department)
(SELECT deptno FROM Depts) =
(SELECT DISTINCT depnto FROM Emps
WHERE job = 'CLERK')
(SELECT deptno FROM Depts) 
(SELECT depnto FROM Emps
WHERE job = 'CLERK')
Both have
the same
meaning!
Rewrite the assertions if employees can be unassigned
© Ellis Cohen 2001-2008
48
Answer with Unassigned Employees
Every department has a clerk
(SELECT deptno FROM Depts) =
(SELECT DISTINCT depnto FROM Emps
WHERE job = 'CLERK'
AND deptno IS NOT NULL)
(SELECT deptno FROM Depts) 
(SELECT depnto FROM Emps
WHERE job = 'CLERK')
© Ellis Cohen 2001-2008
49
Implementing Relational Comparison
If A and B are both tables and
– they have the same attributes
– they do not have any duplicates tuples
– no tuples have NULL values
Then
A  B is equivalent to
(SELECT count(*) FROM
(A NATURAL JOIN B)
=
(SELECT count(*) FROM A)
© Ellis Cohen 2001-2008
50
Uniqueness
Assertions
© Ellis Cohen 2001-2008
51
Uniqueness Exercise
Assuming every employee is
assigned to a department
What's the meaning of
(SELECT DISTINCT deptno FROM Emps
WHERE sal > 3000)
= (SELECT deptno FROM Emps
WHERE sal > 3000)
© Ellis Cohen 2001-2008
52
Unique Relation Comparison
(SELECT DISTINCT deptno FROM Emps
WHERE sal > 3000)
= (SELECT deptno FROM Emps
WHERE sal > 3000)
-- assuming every employee assigned
The depts of employees w sal > 3000 =
The distinct depts of
employees w sal > 3000
No dept has more than one employee
with a salary > 3000
© Ellis Cohen 2001-2008
53
Using the UNIQUE Function
UNIQUE is standard SQL, but not widely
implemented (not in Oracle)
When writing assertions, use UNIQUE
UNIQUE(T)
means
(SELECT DISTINCT * FROM T) =
(SELECT * FROM T)
That is, T does not have duplicate tuples
How would you use UNIQUE to assert:
No department has more than one
employee who makes > 3000?
© Ellis Cohen 2001-2008
54
Solution with Unique
No department has more than one employee who makes > 3000
UNIQUE(
SELECT deptno FROM Emps
WHERE sal > 3000 )
-- assumes every employee assigned
to a department
UNIQUE(
SELECT deptno FROM Emps
WHERE sal > 3000
AND deptno IS NOT NULL )
-- no assumption needed
© Ellis Cohen 2001-2008
55
Alternate Solutions
No department has more than one employee who makes > 3000
(SELECT count(*) FROM Emps
WHERE sal > 3000
GROUP BY deptno) ALL = 1
NOT EXISTS(
SELECT deptno FROM Emps
WHERE sal > 3000
GROUP BY deptno
HAVING count(*) > 1 )
(SELECT DISTINCT deptno FROM Emps
WHERE sal > 3000 AND deptno IS NOT NULL)
= (SELECT deptno FROM Emps
WHERE sal > 3000 AND deptno IS NOT NULL)
-- uses relational comparison (non-standard)
© Ellis Cohen 2001-2008
56