Databaser, efterår 2002 Objektorientering og databaser Troels Andreasen Datalogiafdelingen, hus 42.1 Roskilde Universitetscenter Universitetsvej 1 Postboks 260 4000 Roskilde Telefon: 4674 2000 Fax: 4674 3072 www.dat.ruc.dk
Objektorientering og databaser OQL og SQL99 standarder med betydelig indflydelse OO: OQL ( Ægte objektorienteret) OOprogrammering > RDB verdenen relation spiller kun en lille rolle vi ser IKKE på detaljerne for OQL her OR: SQL99 (Objektrelationel) RDBverdenen > OO programmering kaldet objektrelationel DB centreret omkring relation som begreb udvidelse: mere komplekse typer for tupler mere komplekse domæner for attributter typer/domæner evt. også defineret med metoder Troels Andreasen 2
OR: SQL99 Objekter i SQL99 objekter som komponenter i tupler ("attributetype") rækkeobjekter ("rowtype") Helt centralt definition af typer de såkaldte UDT (UserDefined Types) Troels Andreasen 3
Brugerdefinerede typer (UDT) UDT's kan bruges som type for attribut type for tabel ("rowtype") Herunder Oracle 8i/9i notation og eksempler Kun lille forskel imellem SQL99 og Oracle 8i/9i (vel at mærke: hvis vi holder os til ORdelen) Se også Note N18 (fleste eksempler er herfra) Troels Andreasen 4
UDT Type definition, generel form CREATE TYPE t AS OBJECT (liste af attributter og metoder) ); Eksempel: "PointType: Punkttype" CREATE TYPE PointType AS OBJECT ( x NUMBER, y NUMBER ); Eksempel type baseret på type: "LineType: Linietype" CREATE TYPE LineType AS OBJECT ( end1 PointType, end2 PointType ); Eksempel tabel med attribut baseret på type: "Lines: Tabel med LineTypeattribut" CREATE TABLE Lines ( lineid INT, line LineType ); Troels Andreasen 5
Objektværdier Dannes ved constructor for objekttypen (med samme navn) f.eks. kan værdi for PointType noteres med constructor som PointType(3, 5) Eksempel, "Indsæt 3 Linestupler" INSERT INTO Lines VALUES(27, LineType(PointType(0.0, 0.0), PointType(3.0, 4.0))); INSERT INTO Lines VALUES(28, LineType(PointType(3.0, 4.0), PointType(2.0,7.0))); INSERT INTO Lines VALUES(29, LineType(PointType(2.0,7.0), PointType(0.0, 0.0))); SQL> select * from lines; LINEID LINE(END1(X, Y), END2(X, Y)) 27 LINETYPE(POINTTYPE(0, 0), POINTTYPE(3, 4)) 28 LINETYPE(POINTTYPE(3, 4), POINTTYPE(2, 7)) 29 LINETYPE(POINTTYPE(2, 7), POINTTYPE(0, 0)) SQL> Troels Andreasen 6
Metoder Metode Definers ved erklæring: MEMBER FUNCTION / MEMBER PROCEDURE som del af CREATE TYPE Og udfyldning i CREATE TYPE BODY statement. BODY er en PL/SQL blok Særlig selvreference med SELF Eksempel, length på LineType skaleret med en "scale"parameter CREATE TYPE LineType AS OBJECT ( end1 PointType, end2 PointType, MEMBER FUNCTION length(scale IN NUMBER) RETURN NUMBER, PRAGMA RESTRICT_REFERENCES(length, WNDS) ); / Bemærk "pragma" er et vink til systemet f.eks. DB bliver ikke modificeret: WNDS = write no database state Nødvendig hvis metode skal kunne bruges i forbindelse med forespørgsel Troels Andreasen 7
Metoder Metoder udfyldes med en CREATE BODY.. f.eks. "Length: funktion, der bestemmer længden på linien" CREATE TYPE BODY LineType AS MEMBER FUNCTION length(scale NUMBER) RETURN NUMBER IS BEGIN RETURN scale * SQRT((SELF.end1.xSELF.end2.x)*(SELF.end1.xSELF.end2.x) + (SELF.end1.ySELF.end2.y)*(SELF.end1.ySELF.end2.y) ); END; END; / Troels Andreasen 8
Forespørgsler på relationer med UDT Konponenter tilgås med dotnotation man prikker sig ind som i sædvanlige OOomgivelser (SQL99: bruger i stedet generatormetode X.A() ) Eksempel, "alle tupler i linestabellen" SELECT ll.lineid, ll.line.end1.x x1, ll.line.end1.y y1, ll.line.end2.x x2, ll.line.end2.y y2, ll.line.length(1.0) FROM Lines ll SQL> / LINEID X1 Y1 X2 Y2 LL.LINE.LENGTH(1.0) 27 0 0 3 4 5 28 3 4 2 7 3,16227766 29 2 7 0 0 7,28010989 Troels Andreasen 9
Forespørgsler på relationer med UDT Eksempel, "alle koordinater for første endepunkt" SELECT ll.line.end1.x, ll.line.end1.y FROM Lines ll; END1.X LINE.END1.Y 0 0 3 4 2 7 Eksempel, "koordinater for andet endepunkt" SELECT ll.line.end2 FROM Lines ll; LINE.END2(X, Y) POINTTYPE(3, 4) POINTTYPE(2, 7) POINTTYPE(0, 0) Eksempel, "koordinater for begge" SELECT ll.line FROM Lines ll LINE(END1(X, Y), END2(X, Y)) LINETYPE(POINTTYPE(0, 0), POINTTYPE(3, 4)) LINETYPE(POINTTYPE(3, 4), POINTTYPE(2, 7)) LINETYPE(POINTTYPE(2, 7), POINTTYPE(0, 0)) Troels Andreasen 10
Relationstype (Row type) Relationer/tabeller kan også defineres af given type, f.eks. "Lines1: Tabel af typen LineType" CREATE TABLE Lines1 OF LineType; Svarer (omtrent) til CREATE TABLE Lines1 ( end1 PointType, end2 PointType ); men metoden bliver nu tilgængelig direkte på Lines1 tupler: "gennemsnitlig linielængde": SELECT AVG(ll.length(1.0)) FROM Lines1 ll; Troels Andreasen 11
Relationstype, eksempel fortsat INSERT INTO Lines1 VALUES(PointType(0.0, 0.0), PointType(3.0, 4.0)); INSERT INTO Lines1 VALUES(PointType(3.0, 4.0), PointType(2.0,7.0)); INSERT INTO Lines1 VALUES(PointType(2.0,7.0), PointType(0.0, 0.0)); SELECT * FROM lines1; END1(X, Y) END2(X, Y) POINTTYPE(0, 0) POINTTYPE(3, 4) POINTTYPE(3, 4) POINTTYPE(2, 7) POINTTYPE(2, 7) POINTTYPE(0, 0) "gennemsnitlig linielængde": SELECT AVG(ll.length(1.0)) FROM Lines1 ll; AVG(LL.LENGTH(1.0)) 5,14746252 Troels Andreasen 12
Reference som type Reference type For type t er REF t også en type Udgør referencer til objekter af typen t Med REF kan dannes værdier af en REF ttype udfra tværdier Eksempel, tabel "Lines2: med REF PointType attributter" CREATE TABLE Lines2 ( end1 REF PointType, end2 REF PointType ); der skal først dannes en punkttabel: CREATE TABLE Points OF PointType; INSERT INTO Points VALUES(0.0, 0.0); INSERT INTO Points VALUES(3.0, 4.0); INSERT INTO Points VALUES(2.0,7.0); Herefter: Troels Andreasen 13
Angivelse af REFværdier Eksempel, indsættelse af tupler i Lines2 INSERT INTO Lines2 VALUES((select REF(pp) from points pp where pp.x = 0.0), (select REF(pp) from points pp where pp.x = 3.0)); INSERT INTO Lines2 VALUES((select REF(pp) from points pp where pp.x = 3.0), (select REF(pp) from points pp where pp.x = 2.0)); INSERT INTO Lines2 VALUES((select REF(pp) from points pp where pp.x = 2.0), (select REF(pp) from points pp where pp.x = 0.0)); Troels Andreasen 14
Dereference Dereference med alias "Xkoordinat for første endepunkter": SQL> select end1.x from lines2; select end1.x from lines2 * FEJL i linie 1: ORA00904: ugyldigt kolonnenavn virker ikke, i stedet skrives: select ll.end1.x from lines2 ll; END1.X 0 3 2 Eksplicit dereference "Første endepunkter" select deref(end1) from lines2; DEREF(END1)(X, Y) POINTTYPE(0, 0) POINTTYPE(3, 4) POINTTYPE(2, 7) Troels Andreasen 15
Brug af referencer Restriktioner på brug af referencer refererede objekter skal være tupler af den refererede type (skal findes i en relation og må ikke være attributter) et objekt dannet udenfor en relation kan ikke gives en reference, f.eks. kan IKKE skrives: INSERT INTO Lines2 VALUES(REF(PointType(1,2)), REF(PointType(3,4))) Idet PointType(1,2) og PointType(3,4) ikke er tupler i en relation Sidstnævnte en rimelig restriktion?. Troels Andreasen 16
Troels Andreasen 17 Nestede tabeller Nested tabel En tabel med en attribut, der er af en tabeltype" b a z y x z y x z y x
Nestede tabeller Eksempel, Definition af tabeltype: "PolygonType" CREATE TYPE PolygonType AS TABLE OF PointType; Eksempel, "Nested tabel der bruger PolygonType" CREATE TABLE Polygons ( name VARCHAR2(20), points PolygonType) NESTED TABLE points STORE AS PointsTable; Bemærk Relationer som attributværdier gemmes i en særlig relation for attributten denne relation skal defineres med NESTED TABLE... STORE AS Troels Andreasen 18
Opdatering af nestede tabeller At fylde data i I INSERT skal constructor en for den nestede tabel bruges. attributværdi skal angives som liste af værdier af den pågældende type Eksempel "Indsæt en tupel i Polygons med name= Square ": INSERT INTO Polygons VALUES( 'square', PolygonType(PointType(0.0, 0.0), PointType(0.0, 1.0), PointType(1.0, 0.0), PointType(1.0, 1.0) ) ); Eksempel, "Selektion af samme tupel" SQL> SELECT points 2 FROM Polygons 3 WHERE name = 'square'; POINTS(X, Y) POLYGONTYPE(POINTTYPE(0, 0), POINTTYPE(0, 1), POINTTYPE(1, 0), POINTTYPE(1, 1)) Troels Andreasen 19
Nestede tabeller og THE En nested relation kan refereres direkte i FROM ved THE: f.eks. "xkoordinater for punkter fra polygonen med name=square, der ligger på linien x=y" SQL> SELECT ss.x 2 FROM THE(SELECT points 3 FROM Polygons 4 WHERE name = 'square' 5 ) ss 6 WHERE ss.x = ss.y; X 0 1 Troels Andreasen 20
Nestede tabeller af referencer alternativ til direkte nestede tabeller Eksempel, en alternativ polygontabel med referencer CREATE TYPE PolygonRefType AS TABLE OF REF PointType; CREATE TABLE PolygonsRef ( name VARCHAR2(20), pointsref PolygonRefType) NESTED TABLE pointsref STORE AS PointsRefTable; Som før skal selve punkterne gemmes i en selvstændig relation af typen PointType Bemærk problem at en nested tabels attributter dermed IKKE har noget navn Oracles løsning på dette COLUMN_VALUE Troels Andreasen 21
Nestede tabeller af referencer Eksempel, nested' table uden/med referencer "punkter fra polygonen med name=square, der ligger på linien x=y" i grove træk samme forespørgsel, men COLUMN_VALUE må bruges for at få fat i attributværdier i den nestede tabel Uden referencer SELECT ss.x FROM THE(SELECT points FROM Polygons WHERE name = 'square' ) ss WHERE ss.x = ss.y; Med referencer SELECT ss.column_value.x FROM THE(SELECT pointsref FROM PolygonsRef WHERE name = 'square' ) ss WHERE ss.column_value.x = ss.column_value.y; Troels Andreasen 22
OO + OR: ODL/OQL og SQL99 Programmeringsomgivelser Kommunikation på tværs af DBsprog og værtssprog Relationer/collections Indkapsling Extents Objekt identitet OQL antager en indlejring i et OO sprog antager at objekter OGSÅ er objekter i omgivelserne OQL, nemt I OQL er kernestrukturen snarere collections af objekter ODLklasser er ikke fuldt indkapslede, men opdatering kan kun foregå igennem metoder (skrevet i værtssprog) OQL antager et enkelt extent håndteret for hver klasse alm. ren, skult, systemhåndteret identitet SQL99 antager at objekter IKKE er objekter i omgivelserne SQL99, mere besværligt I SQL99 er relation et centralt begreb (relation ~ row type) attributtyper er, tabeltyper er ikke indkapslede SQL99 kan have 0 eller flere (CREATE TABLE er ikke en del af CREATE TYPE) SQL99 attributtyper skjuler, SQL99 tabeltyper gør det ikke her kan der manipuleres med en OID som med en almindelig værdi fordel: unødige ekstra nøgleattributter undgås Troels Andreasen 23