6b –Basi di dati Relazionali ad oggetti : approfondimenti Tipi definiti dall’utente ID di Oggetti Tabelle innestate Basi di dati II J. Ullman -ORDBMS 1 Fondere i modelli relazionale ed a oggetti I modelli orientati agli oggetti supportano tipi di dati interessanti – non solo file “piatti” Mappe, multimedia, etc. Il modello relazionale supporta query di alto livello I database object-relational sono un tentativo di ottenere il meglio dei due modelli Basi di dati II J. Ullman -ORDBMS 2 Evoluzione dei DBMS I database orientati agli oggetti non hanno avuto successo perché non hanno offerto l’efficienza dei collaudati DBMS relazionali Le estensioni object-relational ai DBMS relazionali catturano molti dei vantaggi dell’ “Object Orientation” mantenendo la relazione come astrazione fondamentale Basi di dati II J. Ullman -ORDBMS 3 Caratteristiche di SQL:1999 e Oracle SQL:1999 include molte delle caratteristiche object-relational che verranno descritte Però, essendo molto recente, diversi DBMS usano approcci ancora differenti Verranno mostrate a volte le caratteristiche e la sintassi di Oracle Basi di dati II J. Ullman -ORDBMS 4 Tipi definiti dall’utente (UDT) Un tipo definito dall’utente, or UDT, è essenzialmente una definizione di classe, con una struttura e dei metodi. Due usi: 1. Come un tipo riga, cioè, il tipo di una relazione. 2. Come il tipo di un attributo di una relazione. Basi di dati II J. Ullman -ORDBMS 5 Definizione di UDT CREATE TYPE <nometipo> AS ( <lista of elementi, come in CREATE TABLE> ); Sintassi di Oracle : 1. Aggiungere “OBJECT” come in CREATE … AS OBJECT. 2. Aggiungere / affinché il tipo sia memorizzato. Basi di dati II J. Ullman -ORDBMS 6 Esempio: definizione di UDT CREATE TYPE BarType AS ( name CHAR(20), addr CHAR(20) ); CREATE TYPE BeerType AS ( name CHAR(20), manf CHAR(20) ); Basi di dati II J. Ullman -ORDBMS 7 Riferimenti SeT è un tipo, allora REF T è il tipo di un riferimento to T, cioè, un “puntatore” ad un oggetto di tipo T. Viene spesso chiamato nei sistemi Object Oriented un “ID di oggetto, OID”. A differenza degli OID, un REF è visibile, anche se normalmente non ha significato Basi di dati II J. Ullman -ORDBMS 8 Esempio: REF CREATE TYPE MenuType AS ( bar REF BarType, beer REF BeerType, price FLOAT ); Gli oggetti MenuType hanno il seguente aspetto: 3.00 Ad un oggetto BarType Basi di dati II Ad un oggetto BeerType J. Ullman -ORDBMS 9 UDT come tipi riga Una tabella può essere definita con uno schema che è un tipo riga, invece di elencare i suoi elementi Sintassi: CREATE TABLE <nome tabella> OF <nome tipo>; Basi di dati II J. Ullman -ORDBMS 10 Esempio: Creare una relazione CREATE TABLE Bars OF BarType; CREATE TABLE Beers OF BeerType; CREATE TABLE Sells OF MenuType; Basi di dati II J. Ullman -ORDBMS 11 Valori di relazioni di tipo riga Tecnicamente, una relazione come Bars, dichiarata con il tipo riga BarType, non è un insieme di coppie - è una relazione unaria , le cui tuple sono oggetti con due componenti: name and addr. Ogni UDT ha un costruttore di tipo con lo stesso nome, che racchiude oggetti di quel tipo. Basi di dati II J. Ullman -ORDBMS 12 Esempio: Costruttore di tipo La query SELECT * FROM Bars; Produce “tuples” come: BarType(’Joe’’s Bar’, ’Maple St.’) Basi di dati II J. Ullman -ORDBMS 13 Accedere ai valori di un tipo riga In Oracle, il punto funziona come di consueto. Ma è necessario, quando vengono impiegate caratteristiche Object Relational, usare un alias per ogni relazione. Esempio: SELECT bb.name, bb.addr FROM Bars bb; Basi di dati II J. Ullman -ORDBMS 14 Accedere ai valori: approccio SQL:1999 In SQL:1999, ogni attributo di un UDT ha un metodo accessore - generator (per ottenere il valore) e un metodo trasformatore – mutator (per cambiare il valore) con lo stesso nome dell’attributo. L’accessore per A non ha argomenti, come A(). Il trasformatore per A prende il nuovo valore come argomento, come in A(v). Basi di dati II J. Ullman -ORDBMS 15 Esempio: accesso ai valori in SQL:1999 La stessa query in SQL:1999 è SELECT bb.name(), bb.addr() FROM Bars bb; Basi di dati II J. Ullman -ORDBMS 16 Metodi costruttori in SQL:1999 Ogni UDT ha almeno un metodo costruttore, ovvero un metodo che ha lo stesso nome del UDT e ritorna un oggetto dello stesso tipo Esempio BarType() Basi di dati II J. Ullman -ORDBMS 17 Inserire valori di tipo riga In Oracle, possiamo usare il comando standard INSERT, ricordando che una relazione di tipo riga è in realtà unaria e richiede quel costruttore di tipo. Esempio: INSERT INTO Bars VALUES( BarType(’Joe’’s Bar’, ’Maple St.’) ); Basi di dati II J. Ullman -ORDBMS 18 Inserire valori: stile di SQL:1999 1. Creare una nuova variabile X del tipo richiesto, usando il costruttore per quel tipo 2. Usare i metodi trasformatori per gli attributi per impostare i valori dei campi di X. 3. Inserire X nella relazione. Basi di dati II J. Ullman -ORDBMS 19 Esempio: INSERT IN SQL:1999 Il codice seguente deve essere parte di una procedura , ad esempio PSM, nel quale abbiamo una variabile newBar. I metodi modificatori cambiano SET newBar = BarType(); i componenti name and addr newBar.name(’Joe’’s Bar’); di newBar newBar.addr(’Maple St.’); INSERT INTO Bars VALUES(newBar); Basi di dati II J. Ullman -ORDBMS 20 UDT come tipi colonna Un UDT può essere il tipo di un attributo. In un’altra definizione di UDT, o in un comando CREATE TABLE, usa il nome dell’ UDT come tipo dell’ attributo. Basi di dati II J. Ullman -ORDBMS 21 Esempio: tipo colonna CREATE TYPE AddrType AS ( street CHAR(30), city CHAR(20), zip INT ); CREATE TABLE Drinkers ( name CHAR(30), addr AddrType, favBeer BeerType ); Basi di dati II J. Ullman -ORDBMS I valori dei componenti addr e favBeer sono oggetti con 3 e 2 campi, rispettivamente. 22 Problema Oracle con l’accesso ai campi Si può accedere ad un campo C di un oggetto che è il valore di un attributo A by A.C. Però, si deve usare un alias, diciamo rr, per la relazione R con attributo A, come rr.A.C. Basi di dati II J. Ullman -ORDBMS 23 Esempio: accesso ai campi in Oracle Sbagliato: SELECT favBeer.name FROM Drinkers; Sbagliato: SELECT Drinkers.favBeer.name FROM Drinkers; Corretto: SELECT dd.favBeer.name FROM Drinkers dd; Basi di dati II J. Ullman -ORDBMS 24 Seguire i REF A -> B ha senso se: 1. A è di tipo REF T. 2. B è un attributo (componente) di oggetti di tipo T. Denota il valore del componente B dell’oggetto puntato da A. Basi di dati II J. Ullman -ORDBMS 25 Esempio: Seguire i REF Ricorda: Sells è una relazione con riga MenuType(bar, beer, price), dove bar and beer sono REF a oggetti di tipo BarType and BeerType. Trova le birre servite da Joe: Poi usa la freccia Per ottenere il nome SELECT ss.beer()->name del bar e della birra referenziati FROM Sells ss WHERE ss.bar()->name = ’Joe’’s Bar’; Prima, i metodi generatori per-ORDBMS Basi di datiusa II J. Ullman accedere alle componenti bar and beer 26 Seguire i REF: Stile Oracle Seguire i REF è implicito nel punto. Basta far seguire un REF da un punto e un campo dell’oggetto riferito. Esempio: SELECT ss.beer.name FROM Sells ss WHERE ss.bar.name = ’Joe’’s Bar’; Basi di dati II J. Ullman -ORDBMS 27 Operatore DEREF di Oracle Motivazione Se vogliamo l’insieme degli oggetti birra per le birre vendute da Joe, possiamo provare: SELECT ss.beer FROM Sells ss WHERE ss.bar.name = ‘Joe’’s Bar’; Legale, ma ss.beer è un REF, quindi senza significato. Basi di dati II J. Ullman -ORDBMS 28 Uso di DEREF in Oracle Per vedere gli oggetti BeerType, si usi: SELECT DEREF(ss.beer) FROM Sells ss WHERE ss.bar.name = ’Joe’’s Bar’; che produce valori tipo: BeerType(’Bud’, ’Anheuser-Busch’) Basi di dati II J. Ullman -ORDBMS 29 Metodi --- Sintassi Oracle Le classi non hanno solo la struttura; possono avere anche metodi. Studieremo la sintassi di Oracle. Si dichiarano in CREATE TYPE, e si definiscono con il comando CREATE TYPE BODY. Useremo la sintassi PL/SQL per i metodi. La variabile SELF si riferisce all’ oggetto al quale il metodo è applicato. Basi di dati II J. Ullman -ORDBMS 30 Esempio: dichiarazione di metodo Si aggiunga il metodo priceInYen a MenuType. CREATE TYPE MenuType AS OBJECT ( bar REF BarType, Il nome dei Metodi beer REF BeerType, in Oracle. price FLOAT, MEMBER FUNCTION priceInYen(rate IN FLOAT) RETURN FLOAT, PRAGMA RESTRICT_REFERENCES(priceInYen, WNDS) ); “Write no database state.” / Cioè, qualunque cosa priceInYen faccia non modificherà il database. Basi di dati II J. Ullman -ORDBMS 31 Definizione di Metodi –Stile di Oracle Forma del comando create-body : CREATE TYPE BODY <type name> AS <definizione dei metodi = definizioni di procedure in PL/SQL , usando “MEMBER FUNCTION” al posto di “PROCEDURE”> END; / Basi di dati II J. Ullman -ORDBMS 32 Esempio: Definizione di Metodi Non c’è il modo (IN) nel body, solo nella dichiarazione CREATE TYPE BODY MenuType AS MEMBER FUNCTION priceInYen(rate FLOAT) RETURN FLOAT IS BEGIN RETURN rate * SELF.price; END; END; Usa le parentesi solo quando c’è almeno / un argomento. Basi di dati II J. Ullman -ORDBMS 33 Uso di un metodo Far seguire il nome di un oggetto da un punto e il nome del metodo,con gli argomenti , se ce ne sono. Esempio: SELECT ss.beer.name, ss.priceInYen(120.0) FROM Sells ss WHERE ss.bar.name = ’Joe’’s Bar’; Basi di dati II J. Ullman -ORDBMS 34 Metodi di ordinamento : SQL:1999 Ogni UDT T può definire due metodi chiamati EQUAL and LESSTHAN. Ognuno prende un argomento di tipo T ed è applicato ad un altro oggetto di tipo T. Ritorna TRUE se e solo se l’oggetto target è = (risp. <) all’oggetto argomento. Consente di comparare oggetti di tipo T mediante =, <, etc. nelle clausole WHERE e per l’ordinamento (ORDER BY). Basi di dati II J. Ullman -ORDBMS 35 Metodi di ordinamento : Oracle Ogni metodo per un UDT può essere dichiarato come un metodo di ordinamento Il metodo di ordinamento restituisce un valore <0, =0, o >0, a seconda che il valore dell’ oggetto SELF is <, =, o > dell’oggetto argomento. Basi di dati II J. Ullman -ORDBMS 36 Esempio: dichiarazione di un metodo di ordinamento. Ordina gli oggetti BarType per nome: CREATE TYPE BarType AS OBJECT ( name CHAR(20), addr CHAR(20), ORDER MEMBER FUNCTION before( bar2 IN BarType) RETURN INT, PRAGMA RESTRICT_REFERENCES(before, WNDS, RNDS, WNPS, RNPS) ); Read/write no database state/package state. Un / Basi di dati II “package” è una collezione of procedure and variabili J. Ullman -ORDBMS Che possono comunicarsi valori tra di loro. 37 Esempio: definizione di un metodo di ordinamento CREATE TYPE BODY BarType AS ORDER MEMBER FUNCTION before(bar2 BarType) RETURN INT IS BEGIN IF SELF.name < bar2.name THEN RETURN –1; ELSIF SELF.name = bar2.name THEN RETURN 0; ELSE RETURN 1; END IF; END; END; /Basi di dati II J. Ullman -ORDBMS 38 Tabelle innestate in ORACLE Il valore di un componente di una tupla può essere un’intera relazione. SeT is a UDT, possiamo creare un tipo S i cui valori sono relazioni con tipo riga T, per mezzo di: CREATE TYPE S AS TABLE OF T ; Basi di dati II J. Ullman -ORDBMS 39 Esempio: tipo tabella innestata CREATE TYPE BeerType AS OBJECT ( name CHAR(20), kind CHAR(10), color CHAR(10) ); / CREATE TYPE BeerTableType AS TABLE OF BeerType; / Basi di dati II J. Ullman -ORDBMS 40 Esempio --- Continua Usa BeerTableType in una relazione Manfs che memorizza l’insieme delle birre prodotte da ciascun produttore in una tupla per quel produttore. CREATE TABLE Manfs ( name CHAR(30), addr CHAR(50), beers beerTableType ); Basi di dati II J. Ullman -ORDBMS 41 Memorizzare relazioni innestate Oracle non memorizza ciascuna relazione innestata come una relazione separata --- fa solo apparire di farlo. Piuttosto, c’è una relazione R in cui tutte le tuple delle tabelle innestate per un attributo A sono memorizzate. Dichiarata nella CREATE TABLE con: NESTED TABLE A STORE AS R Basi di dati II J. Ullman -ORDBMS 42 Esempio: memorizzazione di tabelle innestate CREATE TABLE Manfs ( name CHAR(30), addr CHAR(50), beers beerTableType ) NESTED TABLE beers STORE AS BeerTable; Basi di dati II Si noti dove il punto e virgola va e dove non va. J. Ullman -ORDBMS 43 Interrogare una tabella innestata Possiamo stampare il valore di una tabella innestata come ogni altro valore. Ma questi valori hanno due costruttori di tipo : 1. Per la tabella. 2. Per il tipo delle tuple nella tabella. Basi di dati II J. Ullman -ORDBMS 44 Esempio: interrogare una tabella innestata Trova le birre prodotte da Anheuser-Busch: SELECT beers FROM Manfs WHERE name = ’Anheuser-Busch’; Produce un valore come: BeerTableType( BeerType(’Bud’, ’lager’, ’yellow’), Beertype(’Lite’, ’malt’, ’pale’),… ) Basi di dati II J. Ullman -ORDBMS 45 Interrogazioni con una tabella innestata Una tabella innestata può essere convertita in una relazione ordinaria applicando THE(…). Questa relazione può essere usata nelle clausole FROM come ogni altra relazione. Basi di dati II J. Ullman -ORDBMS 46 Esempio: Uso di THE Trova le ale prodotte da Anheuser-Busch: SELECT bb.name The one nested table for the FROM THE( Anheuser-Busch beers SELECT beers FROM Manfs WHERE name = ’Anheuser-Busch’ ) bb Un alias per la tabella inWHERE bb.kind = ’ale’; nestata, che non ha nome Basi di dati II J. Ullman -ORDBMS 47 Trasformare relazioni in tabelle innestate Ogni relazione con il giusto numero e tipo di attributi può diventare il valore di una tabella innestata. Usa CAST(MULTISET(…) AS <tipo> ) nella relazione per trasformarla nel valore con il giusto tipo per una tabella innestata. Basi di dati II J. Ullman -ORDBMS 48 Esempio: CAST --- 1 Si supponga di avere una relazione Beers(beer, manf), dove beer è un oggetto BeerType e manf una stringa -- il produttore della birra. Vogliamo inserire in Manfs una nuova tupla, con Pete’s Brewing Co. come nome and l’insieme di birre che sono quelle in Beers per Pete’s. Basi di dati II J. Ullman -ORDBMS 49 Esempio: CAST --- 2 INSERT INTO Manfs VALUES ( ’Pete’’s’, ’Palo Alto’, L’insieme di oggetti BeerType per Pete’s CAST( MULTISET( SELECT bb.beer FROM Beers bb WHERE bb.manf = ’Pete’’s’ ) AS BeerTableType ) Trasforma l’insieme di oggetti ); In una relazione innestata Basi di dati II J. Ullman -ORDBMS 50