Databaser, efterår 2002 Begrænsninger i SQL Troels Andreasen Datalogiafdelingen, hus 42.1 Roskilde Universitetscenter Universitetsvej 1 Postboks 260 4000 Roskilde Telefon: 4674 2000 Fax: 4674 3072 www.dat.ruc.dk
Begrænsninger i SQL Begrænsninger afgrænser tilladte forekomster af DB med aktuelle skema detaljerer skema Typer af begrænsninger værdi NOT NULL, entydig værdi, primær-nøgle, fremmed-nøgle domæne delvist ved attribut-check : CHECK <betingelse på attribut> CREATE DOMAIN (SQL3 - dækkes ikke her) CREATE TYPE (bl.a. Oracle og SQL3 - dækkes ikke her) generel integritet delvist ved tupel-check: CHECK <betingelse på tupel> CREATE ASSERTION (ikke Oracle - dækkes ikke her) CREATE TRIGGER (bl.a. Oracle og SQL3) Troels Andreasen 2
NOT NULL, entydig værdi, primær-nøgle kan angives som i CREATE TABLE p ( pid INTEGER, navn VARCHAR2 (70), virksomhedvarchar2 (70), gid INTEGER, land VARCHAR2 (8), kkode INTEGER, UNIQUE (navn), PRIMARY KEY(pid)); eller CREATE TABLE p ( pid INTEGER PRIMARY KEY, navn VARCHAR2 (70) UNIQUE, virksomhed VARCHAR2 (70), gid INTEGER NOT NULL, land VARCHAR2 (8), kkode INTEGER); eller ALTER TABLE p ADD CONSTRAINT PK_p PRIMARY KEY(pid)); ALTER TABLE p ADD CONSTRAINT UNIQ_p UNIQUE (navn)); NOT NULL attribut der skal være specificeret UNIQUE (entydig værdi) en eller flere attributter, der er entydige og derfor også skal være NOT NULL PRIMARY KEY (primær-nøgle) en eller flere attributter, der identificerer (evt. refereres til) og som derfor også er unique kun een pr. relation Indeks på UNIQUE og PRIMARY KEY er implicit dvs. oprettes automatisk af systemet Troels Andreasen 3
Fremmed-nøgle (referenciel integritet) Referenciel integritet en fremmed-nøgle/primærnøgle sammenhæng, der udtrykker det man refererer til skal eksistere en værdi for fremmed-nøglen skal eksistere som værdi for primær-nøglen fremmed-nøgle (foreing key) noteres med REFERENCES CREATE TABLE g ( gid INTEGER PRIMARY KEY, navn VARCHAR2 (70)); CREATE TABLE p ( pid INTEGER PRIMARY KEY, navn VARCHAR2 (70), virksomhed VARCHAR2 (70), gid INTEGER, land VARCHAR2 (8), kkode INTEGER, FOREIGN KEY (gid) REFERENCES g (gid)); gid i p refererer til gid i g en værdi for gid i p skal eksistere i g som værdi for gid Troels Andreasen 4
Fremmed-nøgle (referenciel integritet) Oracle-detalje intet krav om at refererede attributter skal optræde som primær-nøgler (krav i SQL3) MEN hvis refererede attributter er primær-nøgle kan blot skrives FOREIGN KEY (sno) REFERENCES s, i stedet for FOREIGN KEY (sno) REFERENCES s(sno), Troels Andreasen 5
Håndtering af referenciel integritet Metoder til håndtering af ændringer RESTRICT: tillad ikke ændring (default metode) SET NULL: løs problemer ved at indsætte null CASCADE: løs problemer ved følge-ændringer Eksempel R(A,B) og S(A,C), S refererer R ved attribut A create update delete R(A, B) ok restrict cascade restrict set null cascade S(A, C) restrict restrict ok SQL-notation RESTRICT er default, altså skrives blot FOREIGN KEY (A) REFERENCES R SET NULL (understøttes ikke i Oracle - direkte) FOREIGN KEY (A) REFERENCES R ON DELETE SET NULL CASCADE FOREIGN KEY (A) REFERENCES R ON DELETE CASCADE do. med on update Troels Andreasen 6
Eksempel ON DELETE CASCADE CREATE TABLE R (A int, B int, primary key (A)); CREATE TABLE S (A int, C int, FOREIGN KEY (A) REFERENCES R ON DELETE CASCADE); INSERT INTO R VALUES (1,2); INSERT INTO R VALUES (3,4); INSERT INTO S VALUES (1,5); INSERT INTO S VALUES (1,6); INSERT INTO S VALUES (3,7); SQL> SELECT * FROM r; A B 1 2 3 4 SQL> SELECT * FROM s; A C 1 5 1 6 3 7 SQL> delete FROM r where A=1; 1 række er slettet. SQL> SELECT * FROM r; A B 3 4 SQL> SELECT * FROM s; A C 3 7 Troels Andreasen 7
Domæne-begrænsninger ved attribut-check Attribut-check noteres ved en CHECK føjet til attribut-definitionen, som <attribut-navn> <type> CHECK <betingelse> <betingelse> refererer kun aktuelle attribut SQL> CREATE TABLE S (A int, C int CHECK (C<10)); Tabel er oprettet. SQL> INSERT INTO S VALUES (9,9); 1 række er oprettet. SQL> INSERT INTO S VALUES (9,11); INSERT INTO S VALUES (9,11) * FEJL i linie 1: ORA-02290: CHECK-begrænsning (SORT.SYS_C00668) er overtrådt Troels Andreasen 8
Begrænsninger ved tupel-check Tupel-check noteres ved en selvstændig CHECK føjet til tabel-definitionen, som (bl.a.) CHECK <betingelse> <betingelse> refererer kun relationens attributter SQL> CREATE TABLE S (A int, C int, CHECK (A<10 or C<10)); Tabel er oprettet. SQL> INSERT INTO S VALUES (9,11); 1 række er oprettet. SQL> INSERT INTO S VALUES (11,11); INSERT INTO S VALUES (11,11) * FEJL i linie 1: ORA-02290: CHECK-begrænsning (SORT.SYS_C00669) er overtrådt Troels Andreasen 9
Begrænsninger ved tupel-check delforespørgsler er ikke tilladt i Oracle CREATE TABLE S (A int, C int, CHECK (A<10 or A in (SELECT A FROM R))) * FEJL i linie 1: ORA-02251: underforespørgsel er ikke tilladt her Troels Andreasen 10
Begrænsninger ved TRIGGER Trigger en regel med en hændelse en betingelse en aktion hvor aktion bliver udført hvis hændelse indtræffer og betingelse er opfyldt hændelser INSERT, UPDATE eller DELETE eksempel trigger en opret i R ved en opret i S CREATE OR REPLACE TRIGGER MYTRICK BEFORE INSERT ON S FOR EACH ROW WHEN (A < 17) BEGIN INSERT INTO R VALUES (:new.a, 99); END; SQL> SELECT * FROM R; A B 1 2 3 4 SQL> SELECT * FROM S; A C 1 5 1 6 3 7 SQL> INSERT INTO S VALUES (4,77); 1 række er oprettet. SQL> SELECT * FROM R; A B 1 2 3 4 4 99 SQL> SELECT * FROM S; A C 1 5 1 6 3 7 4 77 Troels Andreasen 11
TRIGGER Trigger syntaks "omtrentlig" oracle-syntaks Troels Andreasen 12
TRIGGER OR REPLACE (valgfri): overskriv eventuel eksisterende definition af trigger BEFORE / AFTER / INSTEAD OF INSTEAD OF brugbar ved view hvor f.eks. baserelationer kan modificeres FOR EACH ROW kan undværes (aktionen bliver så udført een gang for relationen) new og old repræsenterer ny og gammel tupel (kun begge er defineret ved UPDATE) Troels Andreasen 13
Trigger til view-opdatering create view indhold as select p.navn pnavn,i.navn inavn from p,ip,i where p.pid=ip.pid and ip.iid=i.iid Skema p(pid, navn, virksomhed, gid, land, kkode) i(iid, navn) ip(iid,pid) g(gid, navn) Troels Andreasen 14
Trigger til view-opdatering CREATE OR REPLACE TRIGGER ViewTrig INSTEAD OF INSERT ON indhold FOR EACH ROW BEGIN INSERT INTO ip SELECT DISTINCT iid,pid FROM p,i WHERE p.navn=:new.pnavn AND i.navn= :new.inavn; END; Troels Andreasen 15
TRIGGER Oracle-problem Underligheder i Oracle problem: Opret en refereret S-tupel, hvis A-værdi for ny S- tupel ikke findes (se også s. 11) snæver syntaks for <condition> CREATE OR REPLACE TRIGGER mytrick BEFORE INSERT ON S FOR EACH ROW WHEN (new.a NOT IN (SELECT A FROM R)) BEGIN INSERT INTO R VALUES (:new.a, 99); END; ikke tilladt snæver syntaks i PL/SQL-blok CREATE OR REPLACE TRIGGER mytrick BEFORE INSERT ON S FOR EACH ROW BEGIN IF NOT EXIST (SELECT * FROM R WHERE A=:new.A) BEGIN INSERT INTO R VALUES (:new.a, 99); END; END; ikke tilladt Troels Andreasen 16
TRIGGER Oracle-problem CREATE OR REPLACE TRIGGER mytrick BEFORE INSERT ON S FOR EACH ROW DECLARE x int; BEGIN SELECT COUNT(*) INTO x FROM R WHERE R.A=:new.A; IF NOT x>0 then INSERT INTO R VALUES (:new.a, 99); END IF; END; SQL> SELECT * FROM R; A B 1 2 3 4 4 99 SQL> SELECT * FROM S; A C 1 5 1 6 3 7 4 77 problemet var: Opret en refereret S-tupel, hvis A-værdi for ny S-tupel ikke findes kan løses således SQL> INSERT INTO S VALUES(27,28); 1 række er oprettet. SQL> SELECT * FROM R; A B 1 2 3 4 4 99 27 99 SQL> SELECT * FROM S; A C 1 5 1 6 3 7 4 77 27 28 Troels Andreasen 17