Ensure that the data is correct.
Relation Predicate: logical AND of all relation constraints
Golden Rule: no update operation may leave any relation in a state violating its predicate
Valid transitions, e.g.
Not valid:
Candidate Key K: set of attributes with
Every relation has at least one candidate key.
If we cannot find any subset of attributes that form a candidate key
we can use the complete set of attributes.
Superkey: unique, but not necessarily irreducible
In case of more than one candidate key: choose one as primary key, the others are alternate keys
Foreign Key: some set of attributes F in relation B, where
The value of F is a reference to the tuple containing C.
Example: value of ORDR.CUST must be equal to an existing value of CUST.ID
Referential Integrity: ensuring valid foreign key values
Referential Actions:
ON DELETE
Trigger: call procedure on event
CREATE DOMAIN COLOR CHAR(6) DEFAULT '???' CONSTRAINT VALID_COLORS CHECK ( VALUE IN ('Red', 'Yellow', 'Blue', 'Green', '???'));
Candidate Keys:
Foreign Keys:
CREATE TABLE SP ...
FOREIGN KEY (SID) REFERENCES S (SID) ON DELETE
Check Constraint: add to column definition, e.g.
.. CHECK (QTY > 0 AND QTY <= 5000)
limitations varying according to DBMS, e.g. Postgres 11 no subqueries
CREATE ASSERTION A1 CHECK ((SELECT MIN(STATUS) FROM S) > 4);
Widely unsupported; e.g. Postgres: ERROR: CREATE ASSERTION is not yet implemented
Related concept: TRIGGER
Call procedure on certain events, such as update on given table
Supported e.g. in Postgres, but sacrifices elegance of declarative SQL, need to write procedural code
Named relational expression
> create view GS as select sid, status, city from S where status > 15; > select * from GS; sid | status | city -------+--------+----------------- S1 | 20 | London S3 | 30 | Paris S4 | 20 | London S5 | 30 | Athens > select * from S; sid | sname | status | city -------+----------------------+--------+----------------- S1 | Smith | 20 | London S2 | Jones | 10 | Paris S3 | Blake | 30 | Paris S4 | Clark | 20 | London S5 | Adams | 30 | Athens
Update:
Postgres 8.3:
> insert into GS values ('S6', 20, 'Vienna'); ERROR: cannot insert into a view HINT: You need an unconditional ON INSERT DO INSTEAD rule.
☆ Postgres 9.3: no problem
Mysql:
> create view GS as select SID, STATUS, CITY from S where STATUS > 15; Query OK, 0 rows affected (0.03 sec) > insert into GS values ('S6', 20, 'Vienna'); Query OK, 1 row affected (0.01 sec) > select * from GS; +-----+--------+--------+ | SID | STATUS | CITY | +-----+--------+--------+ | S1 | 20 | London | | S3 | 30 | Paris | | S4 | 20 | London | | S5 | 30 | Athens | | S6 | 20 | Vienna | +-----+--------+--------+ 5 rows in set (0.00 sec) > select * from S; +-----+-------+--------+--------+ | SID | SNAME | STATUS | CITY | +-----+-------+--------+--------+ | S1 | Smith | 20 | London | | S2 | Jones | 10 | Paris | | S3 | Blake | 30 | Paris | | S4 | Clark | 20 | London | | S5 | Adams | 30 | Athens | | S6 | NULL | 20 | Vienna | +-----+-------+--------+--------+ 6 rows in set (0.00 sec)
Immunity of users and programs to changes in the logical structure of the database (conceptual level)
can be regarded as shorthand for DELETE-INSERT
E.g. Part-Quantity, no suppliers for P7:
insert into P (pid, pname) values ('P7', 'Hammer');
> create view PQ as select PID, sum(QTY) as TOTQTY from SP group by PID; > select * from PQ; pid | totqty --------+-------- P1 | 600 P3 | 400 P5 | 600 P4 | 500 P2 | 1000 P6 | 100
No entry for P7.
Nested subquery representing scalar value:
> select P.PID, (select sum(SP.QTY) from SP where SP.PID = P.PID) as TOTQTY from P; pid | totqty --------+-------- P1 | 600 P2 | 1000 P3 | 400 P4 | 500 P5 | 600 P6 | 100 P7 |
Left join:
select P.PID, sum(QTY) from P left join SP on SP.PID = P.PID group by P.PID; pid | sum --------+------ P1 | 600 P2 | 1000 P3 | 400 P4 | 500 P5 | 600 P6 | 100 P7 |
☆ select P.PID, coalesce(sum(QTY),0) from P left join SP on SP.PID = P.PID group by P.PID;
pid | coalesce --------+---------- P4 | 500 P3 | 400 P1 | 600 P2 | 1000 P6 | 100 P7 | 0 P5 | 600
Postgres:
SELECT table_name,column_name FROM information_schema.columns WHERE data_type = 'numeric'; table_name | column_name ------------+------------- p | weight s | status sp | qty