kako (ne) koristiti objektno-relacijske ...drugom). dakle, nikako ne stoji da "relacijski model =...

25
1 KAKO (NE) KORISTITI OBJEKTNO-RELACIJSKE MOGUĆNOSTI ORACLE DBMS-a Zlatko Sirotić Istra informatički inženjering d.o.o., Pula e-mail: [email protected] SAŽETAK Kasnih 80-tih i ranih 90-tih godina prošlog stoljeća počeli su se pojavljivati prvi objek tni DBMS sustavi, a kasnih 90-tih prvi objektno-relacijski DBMS sustavi. Danas skoro svi RDBMS proizvodi imaju prefiks "O", tj. predstavljaju se kao ORDBMS (objektno-relacijski DBMS), podržavajući (barem neke) objektno-relacijske mogućnosti definirane u SQL:1999 i SQL:2003 standardu. No, poznati znanstvenik na području relacijskog modela i relacijskih sustava C.J.Date napisao je u svojoj knjizi "Database in Depth" (2005, str. 32): "After all, the whole point of an "object/relational" system is precisely that we can have attribute values in relations that are of arbitrary complexity. Perhaps a better way to say it is this: a proper object/relational system is just a relational system with proper type support - which just means it's a proper relational system, no more and no less.". U radu se prikazuju objektno-relacijske mogućnosti Oracle 11g (i 10g) DBMS-a i daju se preporuke na koji bi se način te mogućnosti trebale koristiti (također, na koji način se ne bi trebale koristiti !) u skladu s Dateovim radovima. UVOD Relacijski model podataka teoretski je razradio E.F.Codd i prvi put ga opisao u radu "A Relational Model of Data for Large Shared Data Banks", CACM 13, No. 6 (June 1970). Date (2004, str. 170) navodi da je taj rad i danas vrijedan proučavanja, iako su, naravno, neke ideje u međuvremenu doživjele promjene, ali su te promjene više evolucijske nego revolucionarne. Na temelju relacijskog modela, u desetljeću 1970. -1979. intenzivno se radilo na dizajniranju RDBMS sustava - relacijskih sustava za upravljanje bazama podataka. Prvi ("laboratorijski") sustav razvijen je 1974. u IBM-u (u kojem je tada radio i E.F.Codd), u okviru projekta System R. U tom projektu stvoren je i jezik SEQUEL (Structured English Query Language), čije je ime kasnije skraćeno na SQL. Taj je projekt potaknuo šire zanimanje za relacijski model i za jezik SQL. Prvi komercijalni RDBMS sustav pod imenom Oracle ponudila je 1979. godine kompanija Relational Software Inc. (osnovana je 1977., kasnije je preimenovana u Oracle Corporation). RDBMS sustavi nisu prvi DBMS sustavi na tržištu. Prije njih postojali su hijerarhijski i mrežni DBMS. Međutim, Date ističe (2004, str. 27) da je neprimjereno govoriti o hijerarhijskom i mrežnom modelu podataka, jer su, za razliku od relacijskog modela, hijerarhijski i mrežni "model" nastali nakon pojave tržišnih hijerarhijskih i mrežnih DBMS sustava, pa su "modeli" prikazivali ono što je bilo realizirano u tržišnim produktima. Prvi objektno-orijentirani programski jezik (OOPL) Simula 67 nastao je daleke 1967. godine (autori su mu Kristen Nygaard i Ole-Johan Dahl) dakle, prije pojave relacijskog modela! Jezik Simula 67 inspirirao je kreatore drugih OOPL jezika (npr. jezika Smalltalk, C++, Eiffel). Do naglog razvoja OOPL jezika došlo je početkom i sredinom 80-tih godina prošlog stoljeća. Na krilima uspjeha OOPL-a, kasnih 80-tih i ranih 90-tih godina prošlog stoljeća počeli su se pojavljivati prvi objektni DBMS sustavi, a kasnih 90-tih prvi objektno-relacijski DBMS sustavi. 1. TIPOVI PODATAKA Da bi se prikazao relacijski model, a posebno onaj dio koji govori o strukturi podataka, vrlo je važno definirati tip podataka. Prema (Date 2004, str. 136) tip podataka je imenovani skup vrijednosti koje zadovoljavaju određena ograničenja nad tipom (type constraint). Svakom tipu podataka pridruženi su operatori (read-only i update) za operiranje nad vrijednostima i varijablama toga tipa. Date naglašava da je potrebno uvijek voditi brigu o razlici između vrijednosti i varijable za razliku od vrijednosti, varijabla se može mijenjati, tj. tekuća vrijednost varijable može se zamijeniti nekom drugom vrijednošću. Vrijednosti i varijable uvijek moraju biti određenog tipa.

Upload: others

Post on 30-Jan-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

  • 1

    KAKO (NE) KORISTITI OBJEKTNO-RELACIJSKE MOGUĆNOSTI ORACLE DBMS-a Zlatko Sirotić Istra informatički inženjering d.o.o., Pula e-mail: [email protected]

    SAŽETAK

    Kasnih 80-tih i ranih 90-tih godina prošlog stoljeća počeli su se pojavljivati prvi objektni DBMS

    sustavi, a kasnih 90-tih prvi objektno-relacijski DBMS sustavi. Danas skoro svi RDBMS proizvodi imaju prefiks "O", tj. predstavljaju se kao ORDBMS (objektno-relacijski DBMS), podržavajući (barem neke) objektno-relacijske mogućnosti definirane u SQL:1999 i SQL:2003 standardu.

    No, poznati znanstvenik na području relacijskog modela i relacijskih sustava C.J.Date napisao je u svojoj knjizi "Database in Depth" (2005, str. 32): "After all, the whole point of an "object/relational" system is precisely that we can have attribute values in relations that are of arbitrary complexity. Perhaps a better way to say it is this: a proper object/relational system is just a relational system with proper type support - which just means it's a proper relational system, no more and no less.".

    U radu se prikazuju objektno-relacijske mogućnosti Oracle 11g (i 10g) DBMS-a i daju se preporuke na koji bi se način te mogućnosti trebale koristiti (također, na koji način se ne bi trebale koristiti !) u skladu s Dateovim radovima.

    UVOD Relacijski model podataka teoretski je razradio E.F.Codd i prvi put ga opisao u radu "A Relational

    Model of Data for Large Shared Data Banks", CACM 13, No. 6 (June 1970). Date (2004, str. 170) navodi da je taj rad i danas vrijedan proučavanja, iako su, naravno, neke ideje u međuvremenu doživjele promjene, ali su te promjene više evolucijske nego revolucionarne.

    Na temelju relacijskog modela, u desetljeću 1970.-1979. intenzivno se radilo na dizajniranju RDBMS sustava - relacijskih sustava za upravljanje bazama podataka. Prvi ("laboratorijski") sustav razvijen je 1974. u IBM-u (u kojem je tada radio i E.F.Codd), u okviru projekta System R. U tom projektu stvoren je i jezik SEQUEL (Structured English Query Language), čije je ime kasnije skraćeno na SQL. Taj je projekt potaknuo šire zanimanje za relacijski model i za jezik SQL. Prvi komercijalni RDBMS sustav pod imenom Oracle ponudila je 1979. godine kompanija Relational Software Inc. (osnovana je 1977., kasnije je preimenovana u Oracle Corporation).

    RDBMS sustavi nisu prvi DBMS sustavi na tržištu. Prije njih postojali su hijerarhijski i mrežni DBMS. Međutim, Date ističe (2004, str. 27) da je neprimjereno govoriti o hijerarhijskom i mrežnom modelu podataka, jer su, za razliku od relacijskog modela, hijerarhijski i mrežni "model" nastali nakon pojave tržišnih hijerarhijskih i mrežnih DBMS sustava, pa su "modeli" prikazivali ono što je bilo realizirano u tržišnim produktima.

    Prvi objektno-orijentirani programski jezik (OOPL) Simula 67 nastao je daleke 1967. godine (autori su mu Kristen Nygaard i Ole-Johan Dahl) – dakle, prije pojave relacijskog modela! Jezik Simula 67 inspirirao je kreatore drugih OOPL jezika (npr. jezika Smalltalk, C++, Eiffel). Do naglog razvoja OOPL jezika došlo je početkom i sredinom 80-tih godina prošlog stoljeća. Na krilima uspjeha OOPL-a, kasnih 80-tih i ranih 90-tih godina prošlog stoljeća počeli su se pojavljivati prvi objektni DBMS sustavi, a kasnih 90-tih prvi objektno-relacijski DBMS sustavi.

    1. TIPOVI PODATAKA Da bi se prikazao relacijski model, a posebno onaj dio koji govori o strukturi podataka, vrlo je

    važno definirati tip podataka. Prema (Date 2004, str. 136) tip podataka je imenovani skup vrijednosti koje zadovoljavaju određena ograničenja nad tipom (type constraint). Svakom tipu podataka pridruženi su operatori (read-only i update) za operiranje nad vrijednostima i varijablama toga tipa. Date naglašava da je potrebno uvijek voditi brigu o razlici između vrijednosti i varijable – za razliku od vrijednosti, varijabla se može mijenjati, tj. tekuća vrijednost varijable može se zamijeniti nekom drugom vrijednošću. Vrijednosti i varijable uvijek moraju biti određenog tipa.

  • 2

    Tipovi podataka mogu biti sistemski ili korisnički-definirani. Tipovi podataka mogu biti i skalarni ili neskalarni - skalarni tip nema korisnički-vidljivih komponenti. Tip podataka mora imati jednu (ili više) mogućih (potencijalnih) fizičkih reprezentacija (possible physical representation). Fizička reprezentacija trebala bi korisniku biti sakrivena.

    Date na puno mjesta u (2004) i (2005) navodi da je jezik SQL dosta loša realizacija relacijskog jezika. Zbog lakšeg objašnjavanja relacijskog modela, Date je razvio vlastiti relacijski jezik Tutorial D. Evo kako u jeziku Tutorial D izgleda definicija tipa POINT (geometrijska točka u dvodimenzionalnom prostoru) sa dvije moguće fizičke reprezentacije:

    TYPE POINT

    POSSREP CARTESIAN {X RATIONAL, Y RATIONAL}

    POSSREP POLAR {R RATIONAL, ALFA RATIONAL};

    Date naglašava (2004, str. 116) da je tip POINT skalaran, iako moguće fizičke reprezentacije imaju više komponenti (u ovom slučaju obje reprezentacije imaju po dvije komponente).

    Evo kako u jeziku Tutorial D izgleda definicija ograničenja nad tipom:

    TYPE WEIGHT

    POSSREP {D DECIMAL (5, 1) CONSTRAINT D > 0.0 AND D < 5000.0};

    Osim tipova podataka, Date (2004, str 127) navodi potrebu za postojanjem generatora tipova

    (type generators). Npr. u Tutorial D možemo napisati

    VAR SALES ARRAY INTEGER 12;

    Varijabla SALES je tipa ARRAY INTEGER 12, a ARRAY je generator tipa. U ovom je slučaju ARRAY sistemski generator tipa, ali generatori tipa mogu biti i korisnički-definirani. Generatori tipa poznati su u literaturi i pod drugim imenima, npr. generički tipovi. Meyer (1997, str. 318) ih naziva generičkim apstraktnim tipovima podataka, u Java jeziku zovu se generics, u C++ jeziku zovu se template(s). Date (2004, str. 115) navodi da pojam apstraktni tip podataka (ADT) nije adekvatan, jer na neki način upućuje da postoje i "ne-apstraktni" tipovi podataka, a tip se, po njemu, uvijek treba razlikovati od moguće fizičke reprezentacije.

    Ipak, držimo da Dateova definicija tipa podataka ima nekih dodirnih točaka sa definicijom ADT-a koju prikazuje Meyer u (1997, poglavlje 6). Meyer kaže da apstraktni tipovi podataka predstavljaju teorijsku (matematičku) osnovu za njegovu DBC metodu, pa i za cijeli Eiffel jezik (koji je on dizajnirao) i da nam apstraktni tipovi podataka omogućavaju specificiranje softverskog sustava na precizan i kompletan (koliko je to potrebno) način, ali bez prespecifikacije (overspecification), tj. bez ulaženja u detalje softverskog rješenja. Drugim riječima, ADT omogućavaju da se precizno definira što se želi dobiti, a da se ne mora ulaziti u detalje kako to postići (aplikativni, a ne imperativni pristup). Meyer prikazuje da se definicija ADT-a sastoji od definicije tipova, funkcija, aksioma i pretkondicija.

    Npr. kompletna ADS specifikacija za stog (stack) izgleda ovako (Meyer, 1997, str. 139):

    TYPES

    STACK G FUNCTIONS

    put: STACK G X G STACK G

    remove: STACK G -/ STACK G

    item: STACK G -/ G

    empty: STACK G BOOLEAN

    make: STACK G

    AXIOMS

    For any x: G, s: STACK G

    A1: item (put (s, x)) = x

    A2: remove (put (s, x)) = s

    A3: empty (make)

    A4: not empty (put (s, x)

    PRECONDITIONS

    remove (s: STACK G) require not empty (s)

    item (s: STACK G) require not empty (s)

  • 3

    Slično kao što Dateov Tutorial D jezik ima ograničenja nad tipovima podataka (TYPE…CONSTRAINT), tako Meyer-ov ADT prikazuje ograničenja kroz aksiome i pretkondicije.

    Date naglašava (2004, str. 129-136) da, za razliku od jezika Tutorial D, SQL nema nešto slično CONSTRAINT specifikaciji, pa bi SQL standard definicija skalarnog tipa WEIGHT bila: CREATE TYPE weight AS DECIMAL (5, 1);

    Dalje, SQL ne podržava niti specifikaciju moguće fizičke reprezentacije, već se u SQL-u uvijek

    definira aktualna fizička reprezentacija. Zato će prije navedeni tip POINT, koji je u jeziku Tutorial D bio skalarni tip, u SQL-u biti neskalarni (strukturirani) tip:

    CREATE TYPE point AS (

    x FLOAT,

    y FLOAT

    ) NOT FINAL;

    Napomena: prethodna naredba ima SQL standard sintaksu, a Oracle varijanta iza AS obavezno mora imati riječ OBJECT.

    2. RELACIJSKI MODEL PODATAKA Relacijski model je (matematički) temelj moderne tehnologije baza podataka. Kako kaže Date

    (2005, str. 1-4) poznavanje osnova relacijskog modela važno je za svakog tko se profesionalno bavi bazama podataka, jer profesionalci u svakoj disciplini moraju poznavati temelje svog polja rada. Pritom su važni principi, a ne samo konkretni produkti i tehnologije, jer se principi mijenjaju daleko sporije nego konkretni produkti i tehnologije.

    Danas postoji mnoštvo knjiga koje objašnjavaju relacijski model. Npr. (Date, 2004, 8.izdanje) je fundamentalna (i voluminozna) knjiga koja se široko koristi na sveučilištima širom svijeta i prodana je u preko 750.000 primjeraka. (Date, 2005) je relativno kratka (nešto preko 200 stranica) knjiga namijenjena profesionalcima koji bi htjeli svoje praktično znanje učvrstiti teoretskim temeljima. I na našem jeziku postoji dobra literatura iz tog područja, npr. (Radovan, 1993) i (Varga, 1994).

    Relacijski model (Date, 2004, str. 109) bavi se strukturom podataka (data structure), operacijama nad podacima (data manipulation) i integritetom podataka (data integrity). Ovdje ćemo operacije nad podacima i integritet podataka samo ukratko prikazati. Nešto detaljnije će biti prikazana struktura podataka, jer je to važno za razumijevanje Dateove kritike nekih objektno-relacijskih aspekata SQL:1999 i SQL:2003 standarda (i konkretnih tržišnih ORDBMS sustava koji to podržavaju).

    Najvažniji koncepti u relacijskom modelu jesu relacijska vrijednost ili relacija i relacijska varijabla. No, prvo treba definirati pojam (koristit ćemo engleski termin) tuple vrijednost (tuple value) ili samo tuple.

    (Date 2004, str. 141) definira tuple (value) kao skup uređenih trojki u obliku , gdje i poprima vrijednost 1..n, Ai je ime atributa, Ti je ime tipa, a vi je vrijednost (koja je tipa Ti). Uređeni par je atribut tuple-a. Skup svih atributa je zaglavlje (heading) tuple-a. Tuple tip (tuple type) je determiniran tim zaglavljem. Za razliku od tuple vrijednosti, tuple varijable (tuple variables) nisu dio relacijskog modela, ali su tuple varijable važne za korištenje u host programskom jeziku koji koristimo za pisanje aplikacije (Date 2004, str. 143).

    Relacijska vrijednost (relational value) ili relacija (Date 2004, str. 146) sastoji se od zaglavlja (heading) i tijela (body). Zaglavlje relacije je isto kao i zaglavlje tuple-a. Tijelo relacije je skup svih tuple-a koji imaju isto zaglavlje. Relacijski tip (relational type) je determiniran zaglavljem relacije.

    Date (2004, str. 149) navodi neke važne osobine relacije, koje proizlaze iz činjenice da (matematički) skup po definiciji nema uređenja elemenata i nema duplih elemenata:

    1. atributi su neuređeni u smislu lijevo-desno, 2. tuple-ovi su neuređeni u smislu gore-dolje, 3. relacija nema duplih tuple-ova. Za razliku od prethodno navedenih pojmova relacija, tuple i atribut, SQL koristi pojmove tablica,

    redak i stupac, ali ti pojmovi nisu (potpuno) ekvivalentni. Npr., za razliku od prethodno navedenih osobina relacije, SQL tablica ima uređene stupce, ima uređene retke i može imati duple retke. Date naročito kritizira ovo zadnje.

  • 4

    Osim prethodnog, Date (2004, str. 149) naglašava da su relacije uvijek u 1.normalnoj formi, tj. (suprotno onome što smo uobičajeno učili) vrijednosti u atributima relacije mogu biti druge relacije – to su tzv. RVA (relational-valued attributes). No, to ne znači da Date preporuča takav dizajn relacija – uglavnom preporuča upravo suprotno (2005, str. 143), ali činjenica je da relacijski model to dozvoljava.

    Osim relacija (relacijskih vrijednosti), relacijski model čine i relacijske varijable ili relvar. Date ih (2004, str. 156) dijeli u bazne relvar-e i virtualne relvar-e ili poglede (view). U jeziku Tutorial D sintaksa za deifniranje baznog relvar-a je sljedeća:

    VAR

    BASE

    SQL koristi isti termin tablica i za "tablične vrijednosti" i za "tablične varijable" (Date 2004, str. 163).

    Osim strukture podataka, relacijski model definira i operacije nad podacima, bilo kroz relacijsku algebru, bilo kroz njoj ekvivalentan relacijski račun, ili kroz račun domena (Date 2004, poglavlje 7 i 8), (Radovan 1993, poglavlje 5).

    Što se tiče SQL-a Date (2004, str. 231) napominje da SQL nije baziran niti na relacijskoj algebri, niti na relacijskom računu, već malo na jednome, malo na drugome (a malo ni na jednom, ni na drugom). Dakle, nikako ne stoji da "relacijski model = SQL". No, Date je svjestan (2005, str. 175-176) da se SQL ne može tek tako izbaciti (on vidi SQL kao database COBOL), pa preporuča da se SQL izgradi na temelju (on top) nekog pravog relacijskog jezika i da se, naravno, korisnicima (programerima ili krajnjim korisnicima) dozvoli upotreba (uz SQL) i tog pravog relacijskog jezika.

    Treći dio relacijskog modela, integritet podataka, najviše je zanemaren od strane proizvođača RDBMS sustava, ali je (Date 2004, str. 164) doživio i najveće (evolucijske, ne revolucionarne) promjene u okviru relacijskog modela. Integritetna ograničenja ili samo ograničenja (constraints) Date (2004, str 266) dijeli u 4 kategorije:

    1. ograničenja na razini baze, 2. ograničenja na razini relacijske varijable, 3. ograničenja na razini atributa, 4. ograničenja nad tipom (type constraint). Današnji RDBMS sustavi uz deklarativna ograničenja: PK za primarni ključ, UK za

    jedinstveni ključ, FK za strani ključ, CK za provjeru vrijednosti u jednom retku i NOT NULL (što bi po Dateu trebalo biti obavezno) podržavaju i okidače (triggers). Okidači su u biti procedure i mogu služiti i za druge namjene, a ne samo za očuvanje integriteta podataka. Date preferira deklarativna ograničenja. To ne znači da je on protiv okidača – trebamo ih koristiti dok nemamo (deklarativne) alternative. Date (2004, str 293) navodi da su u zadnje vrijeme integritetna ograničenja ponovno postala zanimljiva – ovaj put pod imenom poslovna pravila (business rules). Poslovna pravila su zapravo user-friendly (tj. manje formalan ili neakademski) način govora o integritetu baze podataka. Date drži taj trend pozitivnim, te preporuča knjige koje je napisao R.G.Ross, jedan od autoriteta na području poslovnih pravila. Dobra knjiga iz područja poslovnih pravila je i Von Halle (2002).

    Još je jedna Dateova napomena (2005, str. 122) vezana je za integritetna ograničenja - ona ne bi trebala biti odgođena (deferred), npr. odgođena do pred kraj transakcije. Naime, za razliku od uobičajenog mišljenja da je transakcija jedinica integriteta (u akronimu ACID - Atomicity, Consistency, Isolation, Durability - to predstavlja Consistency), Date drži da bi naredba (statement) trebala biti jedinica integriteta, pa integritetna ograničenja ne bi smjela biti odgođena.

    Što se tiče teorije dizajna baze podataka (database design teory), koju čine prije svega pravila za normalizaciju podataka, Date joj posvećuje dosta prostora u (2004, poglavlja 11-14) i (2005, poglavlje 7), ali u (2005, str. 136) navodi da teorija dizajna baze podataka nije dio relacijskog modela, već da je ona posebna teorija temeljena (on top) na relacijskom modelu.

    Vezano za normalizaciju podataka, Date navodi (2004, str. 704-709) da se u području skladišta podataka često koriste zvjezdaste sheme (star schema) koje po njegovom mišljenju imaju dosta problema, između ostalog i problema sa normalizacijom. Date ističe (kao negativnu) preporuku "odoli normalizaciji" koju npr. u svojoj knjizi (Kimball, 2002) navodi jedan od autoriteta na području skladišta podataka.

  • 5

    3. NASLJEĐIVANJE TIPOVA

    Nasljeđivanje tipova (type inheritance) ili nasljeđivanje klasa svakako je važno za objektno-orijentirane programske jezike i za objektne DBMS sustave, ali kako tvrdi Date - i za relacijski model i za relacijske DBMS sustave.

    Kod relacijskog modela Date (2004, str. 609) navodi da nas zanima ono što se inače naziva nasljeđivanje domena, što je isto što i nasljeđivanje tipova (podataka), jer su po njemu domena (termin koji se nekad često koristio u okviru relacijskog modela) i tip jedno te isto. Dakle, vrijedi "domena = tip".

    S druge strane, Date smatra i da su tip i klasa jedno te isto. B.Meyer, autoritet na području OOPL-a slaže se da je klasa (i) tip, ali je i modul (1997, str. 170): "U pristupu koji nije objektno orijentiran, koncepti modula i klase jasno su odvojeni. Najvažnije svojstvo pojma klasa je da obuhvaća oba koncepta, stapajući ih u jednu lingvističku tvorevinu. Klasa je modul, ili jedinica dekompozicije softvera. Međutim, klasa je također i tip (ili, u slučajevima u kojima učestvuje generičnost, uzorak tipa).". Dakle, vrijedi "klasa = tip = modul". Napomenimo da je u prethodnom citatu Meyer koristio izraz uzorak (pattern) tipa za ono što Date naziva generator tipa.

    Za razliku od nasljeđivanja tipova (nasljeđivanja domena) što smatra korisnim, Date (2004, str. 609) navodi da je skeptičan prema ideji nasljeđivanja tablica, tj. postojanja (kako ih SQL standard naziva) podtablica i nadtablica (subtables, supertables), s osobinom da podtablica nasljeđuje sve stupce nadtablice i dodaje nove.

    U jeziku Tutorial D, ovako se prikazuje hijerarhija tipova PLANE_FIGURE, ELLIPSE, CIRCLE:

    TYPE PLANE_FIGURE …;

    TYPE ELLIPSE IS PLANE_FIGURE

    POSSREP {

    A LENGTH,

    B LENGTH,

    CTR POINT

    CONSTRAINT A >= B

    };

    TYPE CIRCLE IS ELIPSE

    CONSTRAINT

    THE_A (ELLIPSE) = THE_B (ELLIPSE)

    POSSREP {

    R = THE_A (ELLIPSE)

    CTR = THE_CTR (ELLIPSE)

    };

    Tip ELLIPSE je definiran kao pravi podtip tipa PLANE_FIGURE (PLANE_FIGURE je pravi nadtip tipa ELLIPSE). Tip CIRCLE je podtip tipa ELLIPSE, ali mu je uvedeno ograničenje da je poluos A jednaka poluosi B (tj. ima polumjer R).

    Date (2004, str. 613) navodi da je pravi smisao nasljeđivanja u tome da ako je B podtip tipa A, tada svi operatori (ili, drugim riječima: procedure, funkcije, metode) koji su primjenjivi na tip A istovremeno primjenjivi i na tip B. Dakle, parametri (u drugoj terminologiji - formalni parametri) operatora mogu biti jednog deklariranog tipa, a argumenti (u drugoj terminologiji – aktualni parametri) kod poziva operatora mogu biti ili deklariranog tipa, ili njegovog podtipa. Kaže se (Date 2004, str. 615) da je operator polimorfan. Međutim, u ovom slučaju govorimo o tzv. inkluzijskom polimorfizmu, a postoji i polimorfizam sa preopterećenjem (overloading) operatora, kod kojeg dva ili više operatora imaju isto ime i različite parametre. Međutim, kada se govori o nasljeđivanja tipova (ili nasljeđivanju klasa) pod pojmom polimorfizam misli se na inkluzijski polimorfizam.

    Slično kao kod parametara i argumenata operatora, polimorfnost se manifestira i kod rada sa varijablama. Npr. varijabli E čiji je deklarirani tip ELLIPSE može se pridružiti varijabla C čiji je deklarirani tip CIRCLE. Meyer (1997, str. 467) takvo pridruživanje naziva polimorfno pridruživanje.

    Kod nasljeđivanja tipova, podtip može imati specifičnu implementacijsku verziju određenog operatora. U toku poziva operatora, sistem će sam pozvati odgovarajuću verziju operatora (Date 2004, str. 616), na temelju run-time vezivanja (run-time binding) ili (drugi naziv) dinamičkog vezivanja.

  • 6

    Vezano za nasljeđivanje klasa, Meyer (1997, str. 494) naglašava dvojako značenje nasljeđivanja, koje proizlazi iz dvojne uloge klase – kao tipa i kao modula. Sa stanovišta modula, najvažnija je prednost nasljeđivanja u tome da modul može biti istovremeno i zatvoren i otvoren za mijenjanje (princip otvoren-zatvoren). Naime, metode nadklase mogu biti zatvorene za mijenjanje, ali možemo napraviti podklasu u kojoj ćemo nadjačati (Meyer kaže redefinirati) neku metodu i time je modul postao otvoren.

    Navedimo sada analogan primjer definiranja hijerarhije tipova po SQL standardu (bez definiranja operatora):

    CREATE TYPE plane_figure

    NOT INSTANTIABLE NOT FINAL;

    CREATE TYPE ellipse UNDER plane_figure AS (

    a LENGTH,

    b LENGTH,

    ctr POINT

    ) INSTANTIABLE NOT FINAL;

    CREATE TYPE circle UNDER ellipse AS (

    r LENGTH

    ) INSTANTIABLE NOT FINAL;

    Kako je rečeno i prije, za razliku od jezika Tutorial D, SQL ne podržava ograničenja tipa i moguće fizičke reprezentacije. Zbog toga u SQL-u tip ELLIPSE ima tri atributa (što je u redu), ali podtip CIRCLE ima četiri atributa, a ne dva, koliko bi ih trebao imati. Naravno, atributi a, b, i r u podtipu CIRCLE morali bi imati uvijek jednaku vrijednost, inače dobijamo "ne-okrugli krug".

    Možemo primijetiti da je ovaj nedostatak SQL jezika u odnosu na Tutorial D sličan nedostatku DBC metode (posebno nedostatku invarijanti klase) u OOPL jezicima (npr.) C++ i Java u odnosu na jezik Eiffel (koji podržava DBC).

    4. OBJEKTNO-ORIJENTIRANI (OODBMS) I OBJEKTNO-RELACIJSKI (ORDBMS) SUSTAVI

    Date (2004, str. 813) navodi kako se kasnih 80-tih i ranih 90-tih godina prošlog stoljeća javio velik

    interes za objektno-orijentirane (ili kraće: objektne) DBMS sustave. Jedan od razloga bio je taj što su SQL produkti tada sigurno bili neadekvatni za rješavanje nekih specifičnih aplikacijskih područja kao što su npr. CAD/CAM i CIM sustavi, CASE sustavi, GIS sustavi, specifične znanstvene i medicinske aplikacije, sustavi za pohranu i pretraživanje dokumenata i sl.

    S druge strane, tada su se u upotrebi već dokazali objektno-orijentirani programski jezici, kao što su npr. Smaltalk ili C++. Objektni DBMS sustavi imaju svoj izvor u objektnim programskim jezicima. Kao i objektni programski jezici, tako i objektni DBMS djeluju obećavajuće u smislu povećavanja razine apstrakcije na kojoj se programira. Često se tvrdi da je objektni pristup bliži realnom svijetu, tj. da su softverski objekti slika objekata realnog svijeta. Međutim, kako ističe Meyer (1997, str. 231): "Softverski sistem nije model stvarnosti; u najboljem slučaju to je model modela nekog dijela stvarnosti. Sistem za praćenje pacijenata u bolnici nije model bolnice, već … model modela podskupa bolničke stvarnosti.".

    Treći razlog povećane potrebe (ili želje) za objektnim DBMS sustavom proizlazi također kao posljedica povećane upotrebe OOPL jezika. Naime, programerima je potreban neki sistem perzistencije, koji će omogućiti da se tranzijentni objekti sačuvaju i nakon kraja izvršenja programa, tj. da postanu perzistentni objekti. Naravno, kao mehanizam perzistencije mogu poslužiti (i najčešće to jesu) relacijski DBMS sustavi. Međutim, RDBMS sustavi nisu (ili nisu bili) dobro prilagođeni za pohranjivanje kompleksnih struktura objekata, što se naziva (Meyer 1997, str. 1050) neslaganje impedancije (impedance mismatch) između objektnog modela podataka (objektnog) programskog jezika i relacijskog modela podataka (relacijskog) DBMS sustava. Za rješavanje tog problema često se (Larman 2002, poglavlje 34) koriste (softverski) okviri za perzistenciju (persistence framework), kao skup apstraktnih i konkretnih klasa koje služe za realiziranje servisa za perzistenciju objekata.

    Što se tiče navedena tri razloga za upotrebu ODBMS sustava umjesto RDBMS sustava, može se reći da su današnji RDBMS sustavi puno prilagođeniji za rad sa CAD/CAM i ostalim prije navedenim specifičnim sustavima, jer današnji RDBMS sustavi podržavaju različite tipove podataka koje prije nisu podržavali.

  • 7

    S druge strane, uvođenjem korisnički definiranih tipova podataka i nasljeđivanja tipova, RDBMS sustavi približili su se objektnim sustavima, što znači da je i kod njih povećana razina apstrakcije, a u radu s OOPL jezicima smanjeno je (ali ne i potpuno uklonjeno) neslaganje impedancije.

    Meyer (1997, str. 1053) navodi da je minimalan skup osobina koje objektni DBMS sustav treba imati sljedeći: treba imati one osobine koje ima (relacijska) baza podataka, treba podržavati učahurivanje, identitet objekata i reference. Meyer nasljeđivanje (jednostruko ili višestruko) drži dodatnom, korisnom, ali ne i nužnom osobinom. Osim nasljeđivanja, Meyer kao dodatne mogućnosti navodi: praćenje verzija objekata, praćenje verzija klasa i evolucija sheme, dugačke transakcije, zaključavanje, upite. Blaha i Premerlani (1998, poglavlje 15) ne navodi opće osobine koje treba imati ODBMS sustav, već navodi osobine produkta ObjectStore. Meyer (1997, str. 1056-1057) ukratko opisuje ODBMS sustave Matisse i Versant.

    Zanimljivo je napomenuti da informativno-propagandni materijali firme Matisse Software (www.matisse.com) naglašavaju kako njihov DBMS sustav Matisse predstavlja "Object-SQL Database" (na početnoj web stranici piše da je "Post-Relational SQL Database"). U materijalima ističu da je greška ranih ODBMS sustava upravo u tome što perzistenciju objekata omogućavaju na "prelagan" (tj. nekontroliran) način, te da nijedan DBMS sustav ne može biti uspješan ako ne podržava SQL, i to u samoj jezgri (kernel) DBMS sustava. Ističu kako je njihovo rješenje, tj. objektna-SQL baza, fuzija najboljeg iz oba svijeta – lakoće objektnog razvoja i sveprisutnosti SQL jezika. Možemo primijetiti da se proizvođači RDBMS i ODBMS sustava sve više trude da svoje sustave naprave kao hibridne.

    Što se tiče ODBMS sustava, postojala je organizacija za njihovu standardizaciju – Object Data Management Group (ODMG), u kojoj su se nalazili manje-više svi proizvođači ODBMS sustava. ODMG je napravio standard poznat kao ODMG Object Model, čija je zadnja verzija 3.0 napravljena 2001. godine. ODMG 3.0 definira Object Model, Object Definition Language (ODL), Object Query Language (OQL), ali ne definira nešto kao "Object Manipulation Language", već se manipulacija objektima radi sa programskim jezicima za koje ODMG standard pruža podršku vezivanja jezika (language bindings): C++, Smalltalk i Java. Organizacija ODMG se rasformirala, a pravo na njihov standard preuzela je poznata organizacija (sličnog naziva) Object Management Group (OMG), koja je 2006. objavila da će napraviti "4th generation" standard za objektne baze podataka.

    Treba napomenuti da postoje i razmišljanja o tome da ODBMS (pa ni RDBMS) sustavi uopće nisu potrebni, jer se perzistencija može učiniti dovoljno snažnom već u okviru određenog OOPL jezika. Npr. kod jezika Java poznat je standard Java Data Objects (JDO). Larman (2002, str. 537) mišljenja je da "tehnologije kao one bazirane na JDO specifikaciji nude parcijalna rješenja". Meyer (1997, str. 1058-1060) navodi jedan mehanizam (u jeziku Eiffel) koji bi omogućio da svi objekti budu predefinirani kao perzistentni, a da tranzijentni objekti budu izuzetak. Po njemu, taj mehanizam nalazi potporu u rastućoj dostupnosti 64-bitnog virtualnog adresnog prostora. No, ipak kaže: "Sve je ovo spekulativno i ne pruža nikakav dokaz da bi se trebalo odreći tradicionalnog pojma baze podataka.".

    Prije desetak godina, skoro svi proizvođači relacijskih DBMS sustava izašli su na tržište sa

    objektno-relacijskim nadogradnjama (ili opcijama). Kako navodi Date (2004, str. 859) jasna ideja bila je da njihovi proizvodi trebaju podržavati i objektne i relacijske mogućnosti, tj. proizvodi predstavljaju približavanje između te dvije tehnologije. Dateovo strogo mišljenje je da to približavanje treba ići tako da se zadrže temelji relacijskog modela, koji bi trebao evoluirati tako da uključi dobre osobine objektnih sustava.

    Date je mišljenja da je najvažnija (i možda jedina) dobra ideja koja je uvedena u relacijski model iz objektnog svijeta – odgovarajuća podrška za tipove podataka. Druga dobra ideja (ako se računa odvojeno) je podrška za nasljeđivanje tipova. Zapravo, riječ je o tome da RDBMS sustavi konačno implementiraju nešto što je u relacijskom modelu davno predviđeno, a to su domene, koje jednostavno možemo zvati tipovi podataka. Relacijski sustav koji na pravilan način podržava domene (tj. tipove) može podržavati sve one vrste podataka za koje se prije koristilo ODBMS sustave (CAD/CAM podaci, GIS podaci, multimedija, biomedicinski podaci i dr.).

    Vezano za približavanje između objekata i relacija, Date (2004, str 862) postavlja jedno krucijalno pitanje: "Koji je koncept u relacijskom svijetu blizanac konceptu (objektna) klasa u objektnom svijetu?". Date nudi dva moguća odgovora:

    1. domena = (objektna) klasa, 2. relvar (relacijska varijabla) = klasa. Date kaže da je jedini ispravan odgovor prvi, jer i domena i klasa su zapravo tip. Budući je

    relvar varijabla, a varijable nisu tipovi, drugi odgovor mora biti očito pogrešan.

  • 8

    No, neki produkti polaze od tog pogrešnog odgovora i takvu grešku Date naziva (slobodno prevedeno) prva gruba greška (The First Great Blunder). Iz te greške proizlaze mnoge posljedice pa i ta da se u nekim produktima javlja koncept nadtablice i podtablice (gdje se podtablica kreira kao podklasa nadtablice). Date (2004, str. 869) pretpostavlja da prva gruba greška ima korijenje u nedostatku konsenzusa oko značenja nekih temeljnih termina u objektnom svijetu, a naročito ističe upotrebu termina objekt u "objektnoj analizi i dizajnu" ili "objektnom modeliranju", gdje zapravo nije riječ o objektima, nego o onome što se u području baza podataka obično naziva entitet.

    Druga gruba greška (Date 2004, str. 870) je miješanje pokazivača (pointer) i relacija. Pokazivači pokazuju na varijable, a ne na vrijednosti. Ali, ako relacijska varijabla R1 ima atribut čija je vrijednost pokazivač u relacijsku varijablu R2, tada ti pokazivači pokazuju na tuple varijablu, a pojam tuple varijable ne postoji u relacijskom modelu jer se relacijski model (slobodno rečeno) bavi relacijama (relacijskim vrijednostima) koje su skupovi tuple vrijednosti, koji su pak skupovi skalarnih vrijednosti. Date pretpostavlja da druga gruba greška dolazi od toga što objektni sustavi i objektni jezici uključuju pokazivače kao neku formu objektnog ID-a, pa se onda ideja o miješanju pokazivača i relacija javila iz želje da relacijski sustavi budu što više "object-like".

    5. ORACLE TIPOVI PODATAKA Oracle baza 11g (i prethodne verzije) podržava prije svega sistemski definirane ili ugrađene

    (built-in) tipove podataka (Oracle ih naziva native), koji mogu biti skalarni ("jednostavni") ili neskalarni. Slijedi kratak popis nekih sistemski definiranih skalarnih tipova podataka. Znakovni tipovi podataka su (između ostalih) CHAR za fiksan broj znakova (maksimum je 2000), VARCHAR2 za varijabilan broj znakova (maksimum je 4000), CLOB (Character Large OBject – zapravo, nije riječ o objektu) za veliki broj znakova (4 GB i više). Najvažniji numerički tip podataka je NUMERIC. Najvažniji datumski, a istovremeno i vremenski tip podataka je DATE, koji služi za pamćenje podataka o stoljeću, godini, mjesecu, danu, satu, minuti i sekundi. Ne postoji tip podataka BOOLEAN (odnosno, postoji u PL/SQL-u, ali ne i u SQL-u), kojega Date (2005, str. 165) smatra fundamentalnim tipom podataka.

    Od neskalarnih sistemski definiranih tipova podataka vjerojatno je najzanimljiviji XMLTYPE (uveden je u bazi 9i), koji služi za pohranu XML dokumenata i manipulaciju njima pomoću brojnih ugrađenih metoda (operatora). Iako je riječ o sistemskom tipu podataka, on se koristi na sličan način kao korisnički definirani (user-defined) tipovi podataka. Osim iz SQL-a, XMLTYPE može se koristiti i iz PL/SQL-a i Jave: programske varijable, parametri procedure, povratne vrijednosti funkcije i sl. - mogu biti tipa XMLTYPE.

    Oracle je 1997. godine objavio 8.0 verziju baze i nazvao ju objektno-relacijskom. U skladu s tim nadopunjeni su i SQL i Oracle specifični programski jezik PL/SQL. U bazu 8.0 uvedeni su novi tipovi podataka poznati kao kolekcije (collection; termin se često koristi neprecizno, jer se ponekad misli na tip, a ponekad na objekt tog tipa), kao i objektni tip (object type) za koji možemo reći da je ekvivalent OOPL klasi (napomena: vjerojatno bi pravilnije bilo reći tip objekta, ali zbog lakšeg razumijevanja kod upotrebe tog izraza u rečenicama, koristit ćemo izraz objektni tip – želimo dati naglasak na pojam tip, a ne na pojam objekt). Kolekcije se u Oracle literaturi obično navode zajedno sa objektnim tipom, tj. kolekcije se smatraju objektno-relacijskim mogućnostima (značajkama). Zanimljivo je da su u bazi 8.0 te objektno-relacijske mogućnosti činile opciju koja se posebno prodavala, ali već u bazi 8i Oracle ih je ugradio u standardne (bez posebne doplate) mogućnosti Oracle baze.

    Oracle SQL poznaje dva tipa-kolekcije: tip-ugniježđena tablica (nested table type; uobičajeni ne-Oracle pojam je MULTISET, a mi ćemo ga nazivati tablični tip) i tip-niz (VARRAY type). VARRAY je skraćenica za variable-sized array, ali se definirani broj elemenata može naknadno mijenjati tek od baze 10g. Jezik PL/SQL poznaje još jednu vrstu kolekcije – asocijativne nizove (associative array), koji imaju porijeklo još iz baze Oracle 7, kada su se zvali PL/SQL tablice.

    Primjer definiranja tabličnog tipa:

    CREATE TYPE list_of_names AS TABLE OF VARCHAR2(100)

    /

    Primjer definiranja tipa-niza sa 10 elemenata, te povećanja broja elemenata (od baze 10g) na 20:

    CREATE TYPE array_of_names AS VARRAY(10) OF VARCHAR2(100)

    /

    ALTER TYPE array_of_names MODIFY LIMIT 20 CASCADE

    /

  • 9

    Nažalost, pojedinačnim elementima VARRAY tipa ne može se pristupiti kroz SQL, već samo kroz PL/SQL. Zapravo, jedno (naše) rješenje postoji, ali je poprilično složeno – tekst "Updating the Individual Elements of a Varray" na adresi www.revealnet.com/pipelines/plsql/tips04.htm#JANUARY.

    Objektni tip pojavio se u bazi 8.0, ali u bazi 8i Oracle je stavio naglasak na ugrađivanje JVM (Java Virtual Machine) u bazu - otuda potječe ono "i" (kao Internet) u nazivu 8i. Zanimljivo je pročitati (Feuerstein 2005, str. 982) da se u vrijeme pojave baze 8i smatralo da se programski jezik PL/SQL neće nadograđivati sa novim objektnim mogućnostima. Međutim, objektni tip je u bazi 9i (i u SQL-u i u PL/SQL-u) dobio neke važne objektne mogućnosti kao što su nasljeđivanje, nadjačavanje metoda, polimorfizam. U bazi 10g uvedene su operacije za usporedbu tabličnih tipova i operacije za manipulaciju nad njima (MULTISET operacije, npr. MULTISET UNION, MULTISET INTERSECT i sl.).

    SQL i PL/SQL objektni tip se (barem za sada) može definirati samo kao objekt baze (u određenoj shemi). Objektni tip ima dva dijela - specifikaciju i tijelo. U specifikaciji se deklariraju atributi i metode (funkcije i procedure), a u tijelu se metode (deklarirane u specifikaciji) u potpunosti definiraju. Metode mogu biti statične (STATIC) tj. metode koje se ne primjenjuju na određeni objekt, već na cijelu klasu, te MEMBER metode. U sljedećem primjeru prikazan je objektni tip (samo njegova specifikacija) koji ima dva atributa i tri (MEMBER) metode, od kojih je jedna metoda konstruktor (mora se zvati isto kao objektni tip):

    CREATE OR REPLACE TYPE osoba AS OBJECT (

    ime VARCHAR2 (20),

    tezina_u_kg NUMBER,

    CONSTRUCTOR FUNCTION osoba (

    p_ime VARCHAR2,

    p_tezina_u_kg NUMBER

    ) RETURN SELF AS RESULT,

    MEMBER PROCEDURE prikazi_podatke,

    MEMBER FUNCTION tezina_u_funtama RETURN NUMBER

    ) NOT FINAL

    /

    Budući da prethodni objektni tip nije finalan (označen je sa NOT FINAL), možemo napraviti podklasu i nadjačati bilo koju njenu MEMBER metodu (Oracle STATIC metode ne mogu se nadjačati, već sakriti), jer je default kod metoda NOT FINAL. Npr. u nastavku radimo podklasu prethodne klase i u njoj nadjačavamo metodu PRIKAZI_PODATKE, te uvodimo novu metodu JEDI_MALO_I_DOBRO, koja se dalje ne može nadjačati, jer je označena sa FINAL (a podklasa je označena sa NOT FINAL, kako bi se mogle raditi i njene podklase):

    CREATE OR REPLACE TYPE gurman UNDER osoba (

    omiljena_hrana VARCHAR2(20),

    CONSTRUCTOR FUNCTION gurman (

    p_ime VARCHAR2,

    p_tezina_u_kg NUMBER,

    p_omiljena_hrana VARCHAR2

    ) RETURN SELF AS RESULT,

    OVERRIDING MEMBER PROCEDURE prikazi_podatke,

    FINAL MEMBER PROCEDURE jedi_malo_i_dobro

    ) NOT FINAL

    /

    Oracle objektni tipovi mogu se koristiti za kreiranje perzistentnih objekata (kroz SQL) i za kreiranje tranzijentnih objekata (kroz PL/SQL). Nažalost, za sada Oracle PL/SQL ne podržava reference (ili pokazivače) na tranzijentne objekte (to bi vjerojatno uvelo dodatnu komplikaciju dizajnerima PL/SQL-a – potrebu za automatskim sakupljanjem smeća, jer ne želimo da programer mora sam, kao u jeziku C++, voditi brigu o brisanju nepotrebnih objekata). Kao primjer rada sa tranzijentnim objektima može se pogledati naš tekst "The Template Design Pattern in PL/SQL" na web adresi www.revealnet.com/pipelines/plsql/tips06.htm#OCTOBER).

  • 10

    Jedan drugi naš tekst pokazuje pak moguće greške kod istovremene upotrebe nadjačavanja i preopterećenja metoda - "Dynamic Method Dispatch and Method Overloading in a Subtype" na web adresi www.quest-pipelines.com/newsletter-v4/0503_C.htm.

    Za razliku od referenci na tranzijentne objekte, koje (za sada) ne podržava, Oracle podržava reference na perzistentne objekte, i to ne samo unutar PL/SQL jezika, već i unutar samog SQL-a. To znači da jedna relacija može imati reference na retke druge relacije – to je ono što Date smatra (drugom) grubom greškom. Referentni tip (REF) na neki drugi tip ne definira se u bazi direktno (pomoću CREATE TYPE naredbe), već u okviru neke druge definicije, npr. kao u sljedećem primjeru (REF dept_type):

    CREATE TYPE emp_type AS OBJECT (

    empno NUMBER,

    ename VARCHAR2(20),

    deptno REF dept_type

    )

    /

    U bazi 9i Oracle je uveo i specijalne tipove podataka ANYDATA, ANYDATASET i ANYTYPE. ANYDATA je samoopisujući tip (self-describing) i podržava refleksivnost (kroz odgovarajući API). ANYDATA tip omogućava da stupci (tablice) tog tipa ili (PL/SQL) varijable tog tipa sadrže podatak bilo kojeg sistemski ili korisnički definiranog tipa. ANYDATASET tip je sličan, ali omogućava pohranu skupa podataka (a ne jednog podatka) bilo kojeg tipa. ANYTYPE je tip podataka koji sadrži opis drugog (bilo kojeg) tipa, bez obzira da li je taj drugi tip podataka perzistentan tip (definiran kroz SQL), ili je čak tranzijentan tip, tj. tip podataka koji se generira dinamički za vrijeme izvršavanja (PL/SQL) programa.

    ANYDATA tipovi omogućavaju veliku fleksibilnost u programiranju, ali su zbog svoje fleksibilnosti i teški za razumijevanje, pa su programi koji ih koriste teško čitljivi i mogu biti pogrešno napisani, a greška se pokaže tek kod izvođenja. Ukoliko nam zaista ne treba refleksivno programiranje, bolje ih je ne koristiti. Jedan (naš) primjer korištenja ANYDATA i ANYTYPE tipova podataka je "Inserting a 'Generic Record Type' Using ANYDATA/ANYTYPE Types" na web adresi www.revealnet.com/pipelines/plsql/tips04.htm#MARCH.

    6. ORACLE OBJEKTNO-RELACIJSKE TABLICE Imenom objektne-relacijske tablice (object-relational tables) možemo nazvati one tablice kod

    kojih je jedan ili više stupaca (ali ne redak kao cjelina) temeljen na objektnom tipu ili tipu-kolekciji. Date smatra da su takve vrste tablica sasvim prihvatljive i da su to zapravo relacijske tablice.

    U sljedećem primjeru kreiramo tip ADRESA_T i koristimo ga za definiciju stupca ADRESA u objektno-relacijskoj tablici OSOBA:

    CREATE TYPE adresa_t AS OBJECT (

    grad VARCHAR2(20),

    ulica VARCHAR2(30)

    )

    /

    CREATE TABLE osoba (

    ime VARCHAR2(40) PRIMARY KEY,

    adresa adresa_t

    )

    /

    Kada iz Oracle alata SQL+ pogledamo pomoću naredbe DESCRIBE opis tablice OSOBA, vidjet ćemo da ona ima dva stupca:

    Name Type

    ------ ------------

    IME VARCHAR2(40)

    ADRESA ADRESA_T

  • 11

    Međutim, tablica OSOBA zapravo ima 4 stupca: skalarni stupac IME, dva stupca koja predstavljaju komponente stupca-objekta ADRESA (njihova imena počinju sa SYS), te poseban stupac (dužine 1 byte), koji se zove kao stupac-objekt (u ovom slučaju ADRESA) - njega Oracle koristi za interne potrebe, kao oznaku tipa:

    SELECT segcol#, name, segcollength, type#

    FROM sys.col$

    WHERE obj# =

    (SELECT object_id

    FROM user_objects

    WHERE object_name = 'OSOBA'

    )

    ORDER BY segcol#;

    SEGCOL# NAME SEGCOLLENGTH TYPE#

    ---------- ------------------------------ ------------ ----------

    1 IME 40 1

    2 ADRESA 1 121

    3 SYS_NC00003$ 20 1

    4 SYS_NC00004$ 30 1

    Unos i izmjena redaka nad tablicom OSOBA prikazani su u nastavku. Primijetimo da se kod unosa vrijednosti neskalarnog stupca ADRESA mora pozvati (default) konstruktor ADRESA_T, a kod izmjene komponente neskalarnog tipa mora se koristiti alias tablice, dok se kod izmjene kompletnog skalarnog stupca opet koristi konstruktor (a alias tablice nije nužan):

    INSERT INTO osoba VALUES (

    'Ana',

    adresa_t ('G1', 'U1')

    );

    UPDATE osoba o

    SET o.adresa.ulica = 'U2'

    WHERE ime = 'Ana';

    UPDATE osoba

    SET adresa = adresa_t ('G2', 'U3')

    WHERE ime = 'Ana';

    Slijede dvije varijante SELECT naredbe nad tablicom OSOBA – prva selektira neskalarni stupac kao cjelinu, a druga selektira komponente skalarnog stupca (u drugom slučaju je nužan alias tablice):

    SELECT ime, adresa

    FROM osoba;

    IME ADRESA(GRAD, ULICA)

    ---- -----------------------

    Ana ADRESA_T('G2', 'U3')

    SELECT ime,

    o.adresa.grad,

    o.adresa.ulica

    FROM osoba o;

    IME ADRESA.GRAD ADRESA.ULICA

    ---- ----------- ------------

    Ana G2 U3

    Izbrišimo sada tablicu i tip, da nam ne smetaju u nastavku: DROP TABLE osoba;

    DROP TYPE adresa_t;

  • 12

    Prikažimo sada kako izgleda nasljeđivanje tipova podataka, nadjačavanje metoda i polimorfizam kod objektno-relacijskih tablica. Prvo ćemo kreirati nadtip ADRESA_T:

    CREATE TYPE adresa_t AS OBJECT (

    grad VARCHAR2(20),

    ulica VARCHAR2(30),

    MEMBER FUNCTION adresa_f RETURN VARCHAR2

    ) NOT FINAL -- OBAVEZNO

    /

    CREATE TYPE BODY adresa_t AS

    MEMBER FUNCTION adresa_f RETURN VARCHAR2 IS

    BEGIN

    RETURN 'Generalna adresa:' || grad || ' ' || ulica;

    END;

    END;

    /

    Kreirajmo sada tablicu OSOBA i unesimo jedan redak:

    CREATE TABLE osoba (

    ime VARCHAR2(40) PRIMARY KEY,

    adresa adresa_t

    );

    INSERT INTO osoba VALUES (

    'Ana',

    adresa_t ('G1', 'U1')

    );

    Kreirajmo sada podtipove KUCNA_ADRESA_T i POSL_ADRESA_T, u kojima ćemo dodati atribute i nadjačati metodu (funkciju) ADRESA_F:

    CREATE TYPE kucna_adresa_t UNDER adresa_t (

    dodatak1 VARCHAR2(11),

    OVERRIDING MEMBER FUNCTION adresa_f RETURN VARCHAR2

    );

    /

    CREATE TYPE BODY kucna_adresa_t AS

    OVERRIDING MEMBER FUNCTION adresa_f RETURN VARCHAR2 IS

    BEGIN

    RETURN 'Kućna adresa:' || grad || ' ' || ulica || ' ' || dodatak1;

    END;

    END;

    /

    CREATE TYPE posl_adresa_t UNDER adresa_t (

    dodatak1 VARCHAR2(12),

    dodatak2 VARCHAR2(13),

    dodatak3 VARCHAR2(14),

    OVERRIDING MEMBER FUNCTION adresa_f RETURN VARCHAR2

    );

    /

    CREATE TYPE BODY posl_adresa_t AS

    OVERRIDING MEMBER FUNCTION adresa_f RETURN VARCHAR2 IS

    BEGIN

    RETURN 'Poslovna adresa:' || grad || ' ' || ulica || ' ' ||

    dodatak1 || ' ' || dodatak2 || ' ' || dodatak3;

    END;

    END;

    /

  • 13

    Sada možemo unijeti retke sa konstruktorima podtipova KUCNA_ADRESA_T, POSL_ADRESA_T, jer se tablica OSOBA automatski proširila sa 4 dodatna stupca (1 + 3):

    SELECT segcol#, name, segcollength, type#

    FROM sys.col$

    WHERE obj# =

    (SELECT object_id

    FROM user_objects

    WHERE object_name = 'OSOBA'

    )

    ORDER BY segcol#;

    SEGCOL# NAME SEGCOLLENGTH TYPE#

    ---------- ------------------------------ ------------ ----------

    1 IME 40 1

    2 ADRESA 256 121

    3 SYS_NC00003$ 16 23

    4 SYS_NC00004$ 20 1

    5 SYS_NC00005$ 30 1

    6 SYS_NC00006$ 11 1

    7 SYS_NC00007$ 12 1

    8 SYS_NC00008$ 13 1

    9 SYS_NC00009$ 14 1

    INSERT INTO osoba VALUES (

    'Pero',

    kucna_adresa_t ('G2', 'U2', 'D1')

    );

    INSERT INTO osoba VALUES (

    'Mira',

    posl_adresa_t ('G3', 'U3', 'D1', 'D2', 'D3')

    );

    Sada možemo propustiti dvije varijante SELECT naredbe – u prvoj se navode imena stupaca, a u drugoj se navodi ime stupca i ime metode (funkcije). Vidimo da u drugom SELECT-u moramo koristiti alias tablice i zagrade iza imena metode, iako (u ovom slučaju) metoda nema parametara:

    SELECT ime, adresa

    FROM osoba;

    IME ADRESA(GRAD, ULICA)

    ---- --------------------------

    Ana ADRESA_T('G1', 'U1')

    Pero KUCNA_ADRESA_T('G2', 'U2', 'D1')

    Mira POSL_ADRESA_T('G3', 'U3', 'D1', 'D2', 'D3')

    -- obavezne zagrade iza imena metode (PL/SQL ima uniformni pristup, SQL ne)

    SELECT ime, o.adresa.adresa_f()

    FROM osoba o;

    IME O.ADRESA.ADRESA_F()

    ---- ---------------------

    Ana Generalna adresa:G1 U1

    Pero Kućna adresa:G2 U2 D1

    Mira Poslovna adresa:G3 U3 D1 D2 D3

  • 14

    Dalje - selekcija na retke kojima je adresa određenog tipa

    -- samo tip kucna_adresa_t ili njegovi podtipovi (sada ih nema)

    SELECT ime, adresa

    FROM osoba

    WHERE adresa IS OF (kucna_adresa_t);

    -- samo tip adresa_t ili njegovi podtipovi (sada su to svi)

    SELECT ime, adresa

    FROM osoba

    WHERE adresa IS OF (adresa_t);

    -- samo tip adresa_t, bez podtipova

    SELECT ime, adresa

    FROM osoba

    WHERE adresa IS OF (ONLY adresa_t);

    Kako prikazati samo određene atribute objektnog stupca (one koji odgovaraju određenim

    atributima iz nadtipa adresa ili iz njegovih podtipova)? Atribute koji odgovaraju atributima iz nadtipa adresa možemo lako prikazati:

    SELECT ime, o.adresa.grad FROM osoba o;

    IME ADRESA.GRAD

    ---------------------------------------- --------------------

    Ana G1

    Pero G2

    Mira G3

    Ali, ne možemo (direktno) prikazati atribute koji odgovaraju atributima podtipa:

    SELECT ime, o.adresa.dodatak1

    FROM osoba o;

    ERROR at line 1: ORA-00904: "O"."ADRESA"."DODATAK1": invalid identifier

    Istina, moguće je navesti sistemsko ime stupca:

    SELECT ime, SYS_NC00009$ FROM osoba;

    No, "čišće" je koristiti TREAT ("object_column" AS "subtype"):

    SELECT ime, TREAT (adresa AS posl_adresa_t).dodatak1

    FROM osoba;

    IME TREAT(ADRESA

    ---------------------------------------- ------------

    Ana

    Pero

    Mira D1

    Ili, prikažimo samo osobe koje imaju poslovnu adresu:

    SELECT ime, TREAT (adresa AS posl_adresa_t).dodatak1

    FROM osoba

    WHERE adresa IS OF (posl_adresa_t);

    IME TREAT(ADRESA

    ---------------------------------------- ------------

    Mira D1

  • 15

    Kako raditi UPDATE objektnog stupca – cijelog ili pojedinih atributa? Kako smo i prije vidjeli, lako je ažurirati cijeli stupac:

    UPDATE osoba

    SET adresa = adresa_t ('G2', 'U3')

    WHERE ime = 'Ana';

    Možemo ažurirati i atribute objektnog stupca koji odgovaraju atributima iz nadtipa adresa:

    UPDATE osoba o

    SET o.adresa.grad = 'G3'

    WHERE ime = 'Ana';

    Ali, ne možemo (direktno) ažurirati atribute koji odgovaraju atributima podtipa (npr. podtipa

    posl_adresa_t). Napomenimo da u sljedećoj naredbi razlog greške nije taj što 'Ana' ima generalnu adresu (tipa adresa_t) koja nema stupac dodatak1 – isto bi bilo sa 'Pero' i 'Mira', iako njihove adrese (tipa kucna_adresa_t i posl_adresa_t) imaju taj stupac:

    UPDATE osoba o

    SET o.adresa.dodatak1 = 'D2'

    WHERE ime = 'Ana';

    SET o.adresa.dodatak1 = 'D2'

    *

    ERROR at line 2:

    ORA-00904: "O"."ADRESA"."DODATAK1": invalid identifier

    Istina, mogli bismo koristiti sistemska imena stupaca dodatak1 (napomena - imamo ih dva), kao kod SELECT, ali to nije "čisto". No, za razliku od SELECT, kod UPDATE ne pomaže TREAT:

    UPDATE osoba o

    SET TREAT (adresa AS posl_adresa_t).dodatak1 = 'D2'

    WHERE ime = 'Ana';

    SET TREAT (adresa AS posl_adresa_t).dodatak1 = 'D2'

    *

    ERROR at line 2:

    ORA-00927: missing equal sign

    Ali, ovo radi - UPDATE inline wiew:

    UPDATE (SELECT TREAT (adresa AS posl_adresa_t).dodatak1 dod1

    FROM osoba

    WHERE ime = 'Ana'

    )

    SET dod1 = 'D2';

    ili

    UPDATE (SELECT ime,

    TREAT (adresa AS posl_adresa_t).dodatak1 dod1

    FROM osoba

    )

    SET dod1 = 'D2'

    WHERE ime = 'Ana';

    Nažalost, moramo primijetiti da smo u ovom konkretnom slučaju dobili nekonzistentnost,

    iako u UPDATE nismo koristili sistemsko ime stupca (što nije "čisto"). Naime, 'Ana' sada ima napunjen stupac dodatak1, iako je njena adresa i dalje ostala tipa adresa_t, a adresa_t nema taj stupac.

  • 16

    Kako napraviti INDEX ili CONSTRAINT nad atributima objektnog stupca? Ne mora se koristiti "sistemsko ime" (u sljedećoj točki vidjet ćemo da ponekad moramo, npr. kod

    FK i objektnih tablica, u nekim slučajevima), može i ovako:

    CREATE INDEX dodatak3_i ON osoba

    (TREAT (adresa AS posl_adresa_t).dodatak3);

    Izbrišimo opet tablice i tipove, da nam ne smetaju u nastavku (to ćemo raditi i poslije):

    DROP TABLE osoba;

    DROP TYPE posl_adresa_t;

    DROP TYPE kucna_adresa_t;

    DROP TYPE adresa_t;

    Pogledajmo sada kako bi izgledala tablica u kojoj je stupac TELEFONI deklariran kao

    NIZ_TELEFONA_T (niz ima pet elemenata). Elementi niza u ovom slučaju su skalarne vrijednosti, ali mogu biti i neskalarne. Primijetimo da kod INSERT naredbe nije nužno navesti sve elemente niza (navedena su samo dva telefona):

    CREATE TYPE niz_telefona_t AS VARRAY (5) OF VARCHAR2(20)

    /

    CREATE TABLE osoba (

    ime VARCHAR2(40) PRIMARY KEY,

    telefoni niz_telefona_t

    )

    /

    INSERT INTO osoba VALUES (

    'Mira',

    niz_telefona_t ('12345', '54321')

    );

    DROP TABLE osoba;

    DROP TYPE niz_telefona_t;

    Kako smo već naveli u 5.poglavlju, pojedinačnim elementima VARRAY tipa ne može se pristupiti kroz SQL (osim na vrlo složen način), već samo kroz PL/SQL. Zato u Oracle bazi nije preporučljivo koristiti VARRAY tip za stupce tablice.

    Na kraju, pogledajmo kako objektno-relacijska tablica OSOBA može imati stupac čija je vrijednost

    neki skup redaka telefona. Za takav slučaj uobičajeno bi se reklo da tablica OSOBA nije u 1.normalnoj formi, ali (kako smo vidjeli u 2.poglavlju) Date naglašava da ta tablica jeste u 1.normalnoj formi ali je njen atribut TELEFONI tzv. RVA (relational-valued attribute). Oracle to zove ugniježđena tablica (nested table):

    CREATE TYPE telefon_t AS OBJECT (

    vrsta VARCHAR(10),

    broj VARCHAR2(20)

    )

    /

    CREATE TYPE tablica_telefona_t AS TABLE OF telefon_t

    /

    CREATE TABLE osoba (

    ime VARCHAR2(40) PRIMARY KEY,

    telefoni tablica_telefona_t

    ) NESTED TABLE telefoni STORE AS telefoni_tab

    /

  • 17

    Vidimo da se u stvarnosti stupac TELEFONI realizira kao odvojena tablica TELEFONI_TAB. Interno, tablice-roditelj OSOBA i tablica-dijete TELEFONI_TAB imaju dodatne stupce koji služe za njihovo povezivanje. No, kako kaže Date, nije važna interna realizacija, već vanjski pogled (korisnika, uključujući i programera). Evo kako bi izgledao INSERT nad tablicom OSOBA:

    INSERT INTO osoba VALUES (

    'Ana',

    tablica_telefona_t (

    telefon_t ('kućni', '123'),

    telefon_t ('posl.', '456'),

    telefon_t ('mobil', '789')

    )

    );

    UPDATE možemo raditi na dva načina. Prvi način, mijenjanje vrijednosti cijelog RVA stupca

    TELEFONI, je jednostavniji:

    UPDATE osoba

    SET telefoni =

    tablica_telefona_t (

    telefon_t ('posl.', '000'),

    telefon_t ('mobil', '111')

    )

    WHERE ime = 'Ana';

    U drugom načinu mijenjamo samo neke retke ugniježđene tablice (nula, jedan ili više), ali uvijek retke-djecu koji pripadaju odabranom (samo jednom) retku-roditelju, inače Oracle javlja grešku (u nastavku mijenjamo samo telefone koji pripadaju osobi Ana; konkretno mijenjamo samo jedan telefon). U ovom načinu moramo koristiti operator TABLE, kojim pretvaramo odabrani skup redaka ugniježđene tablice u virtualnu tablicu:

    UPDATE

    TABLE (SELECT telefoni

    FROM osoba

    WHERE ime = 'Ana'

    )

    SET broj = '111'

    WHERE vrsta = 'kućni';

    DROP TABLE osoba;

    DROP TYPE tablica_telefona_t;

    DROP TYPE telefon_t;

    Tablice sa RVA stupcima najčešće nisu dobar dizajnerski izbor, jer sa njima model podataka sliči na nekadašnje hijerarhijske baze podataka, u kojima se tablici-djetetu moglo pristupati samo preko tablice-roditelja, a rijetko u stvarnosti imamo tablice kojima ne želimo pristupati i direktno. Kako smo već rekli u 2.poglavlju, i Date (2005, str. 143) drži da RVA atributi najčešće nisu dobar dizajnerski izbor, iako su u relacijskom modelu dozvoljeni.

    Inače, poznati Oracle ekspert (i Oracle zaposlenik) Tom Kyte kaže (2005, str. 417) da on uopće ne upotrebljava objektno-relacijske ili objektne tablice, već koristi objektne mogućnosti unutar jezika PL/SQL i koristi objektne poglede (object views) napravljene nad relacijskim tablicama.

  • 18

    7. ORACLE OBJEKTNE TABLICE

    Za razliku od objektno-relacijskih tablica, kod kojih je stupac tablice temeljen na objektnom tipu ili

    tipu-kolekciji, Oracle objektne tablice ili tablice objekata (object tables) su one tablice kod kojih cijeli redak reprezentira jedan objekt - to je onaj slučaj koji Date naziva prvom grubom greškom (napomena: kao i kod izraza objektni tip u odnosu na izraz tip objekata, tako nam se i izraz objektna tablica čini pogodnijim za upotrebu od izraza tablica objekata).

    Evo kako izgleda objektna tablica ODJEL, temeljena na objektnom tipu ODJEL_T:

    CREATE TYPE odjel_t AS OBJECT (

    sifra VARCHAR(10),

    naziv VARCHAR2(20)

    )

    /

    CREATE TABLE odjel OF odjel_t

    (PRIMARY KEY (sifra)) OBJECT IDENTIFIER IS PRIMARY KEY

    /

    Tablici ODJEL definiran je primarni ključ na temelju stupca SIFRA. Oracle bi tablici automatski

    kreirao i nevidljivi stupac za object identifier – OID (plus još jedan nevidljivi stupac za oznaku tipa), ali smo klauzulom OBJECT IDENTIFIER IS PRIMARY KEY kazali da će primarni ključ biti zamjena za pravi OID.

    INSERT, SELECT i UPDATE naredbe nad objektnom tablicom ODJEL izgledaju isto kao naredbe nad običnom relacijskom tablicom (kako je pokazano, INSERT možemo raditi i pomoću konstruktora, ali jednostavnije je bez njega):

    INSERT INTO odjel VALUES ('10', 'Analiza');

    INSERT INTO odjel VALUES (odjel_t ('20', 'Dizajn'));

    SELECT sifra, naziv

    FROM odjel;

    SIFRA NAZIV

    ---------- --------

    10 Analiza

    20 Dizajn

    UPDATE odjel

    SET naziv = 'Design'

    WHERE SIFRA = '20';

    Sada ćemo definirati objektni tip RADNIK_T koji ima referencu na objektni tip ODJEL_T, te ćemo na temelju objektnog tipa RADNIK_T napraviti objektnu tablicu RADNIK:

    CREATE TYPE radnik_t AS OBJECT (

    sifra VARCHAR(10),

    naziv VARCHAR2(20),

    odjel_oid REF odjel_t

    )

    /

    CREATE TABLE radnik OF radnik_t

    (PRIMARY KEY (sifra)) OBJECT IDENTIFIER IS PRIMARY KEY

    /

    ALTER TABLE radnik MODIFY odjel_oid NOT NULL;

    ALTER TABLE radnik ADD SCOPE FOR (odjel_oid) IS odjel;

  • 19

    Sa SCOPE FOR (ODJEL_OID) IS ODJEL ograničili smo referencu ODJEL_OID tako da pokazuje na OID (baš) tablice ODJEL, a ne na OID neke druge objektne tablice koja je napravljena na temelju objektnog tipa ODJEL_T. Mogućnost da više objektnih tablica bude kreirano na temelju istog objektnog tipa Date drži (lošom) posljedicom prve grube greške. Inače, napomenimo da se reference mogu koristiti ne samo kod deklaracije objektnog tipa, nego i stupac objektno-relacijske tablice može biti deklariran kao referenca na objektni tip (što znači da i objektno-relacijska tablica može imati referencu na objektnu tablicu).

    Tablicu RADNIK sada ćemo napuniti sa dva retka:

    INSERT INTO radnik VALUES (

    '101', 'Ana',

    (SELECT REF (o)

    FROM odjel o

    WHERE sifra = '10'

    )

    );

    INSERT INTO radnik VALUES (

    '102', 'Pero',

    (SELECT REF (o)

    FROM odjel o

    WHERE sifra = '20'

    )

    );

    Sada ćemo vidjeti kako se nad objektnom tablicom (ponekad) može napraviti upit bez JOIN-a. Naime, baza sama napravi JOIN – to je tzv. implicitno dereferenciranje referenci (implicit dereferencig of REFs). Ta mogućnost na prvi pogled djeluje spektakularno, ali kako kaže Date (2004, str 881-882), to je samo sintaktička skraćenica i nije jasno kada se smije, a kada se ne smije koristiti:

    SELECT sifra,

    naziv,

    r.odjel_oid.naziv

    FROM radnik r;

    SIFRA NAZIV ODJEL_OID.NAZIV

    ------ ------ ----------------

    101 Ana Analiza

    102 Pero Dizajn

    Nažalost, klauzula SCOPE FOR ne osigurava referencijalni integritet, jer ćemo uspjeti izbrisati odjel 20 (Dizajn) u kojem radi neki radnik (konkretno, Pero):

    DELETE odjel

    WHERE sifra = '20';

    SELECT sifra,

    naziv,

    r.odjel_oid.naziv

    FROM radnik r;

    SIFRA NAZIV ODJEL_OID.NAZIV

    ------ ------ ----------------

    101 Ana Analiza

    102 Pero

  • 20

    Reference koje pokazuju na nepostojeći objekt zovu se viseće reference (dangling REFs). Ako želimo izbjeći viseće reference, tj. osigurati referencijalni integritet (a u pravilu želimo), moramo tablici RADNIK kreirati vanjski ključ na tablicu ODJEL:

    -- Dodavanje FK neće proći sa tekućim podacima, jer je narušen integritet:

    -- ORA-02298: cannot validate (OBUKA.RADNIK_ODJEL_FK) parent keys not found

    -- Zato moramo dodati redak roditelja (kojega smo prije izbrisali)

    INSERT INTO odjel VALUES

    (odjel_t ('20', 'Dizajn'));

    ALTER TABLE radnik

    ADD CONSTRAINT radnik_odjel_fk

    FOREIGN KEY (odjel_oid) REFERENCES odjel;

    DROP TABLE radnik;

    DROP TYPE radnik_t;

    Pogledajmo malo kako idu zajedno nasljeđivanje i objektne tablice. Napravit ćemo dva objektna

    tipa - RADNIK_T (radi jednostavnosti ovdje nećemo raditi reference na tip ODJEL_T) i PROGRAMER_T, od kojih je drugi podtip prvoga. Te objektne tipove koristit ćemo na dva različita načina. U prvom načinu pokušat ćemo ih koristiti za kreiranje nadtablice i podtablice:

    CREATE TYPE radnik_t AS OBJECT (

    sifra VARCHAR(10),

    naziv VARCHAR2(20),

    odjel_sifra VARCHAR2(10)

    ) NOT FINAL

    /

    CREATE TABLE radnik OF radnik_t

    (PRIMARY KEY (sifra)) OBJECT IDENTIFIER IS PRIMARY KEY

    /

    ALTER TABLE radnik

    ADD CONSTRAINT radnik_odjel_fk

    FOREIGN KEY (odjel_sifra) REFERENCES odjel (sifra);

    INSERT INTO radnik VALUES

    ('101','Ana','10');

    INSERT INTO radnik VALUES

    ('102','Pero','20');

    CREATE TYPE prog_jezik_t AS OBJECT (

    sifra VARCHAR(10),

    naziv VARCHAR2(20)

    ) NOT FINAL

    /

    CREATE TABLE prog_jezik OF prog_jezik_t

    (PRIMARY KEY (sifra)) OBJECT IDENTIFIER IS PRIMARY KEY

    /

    INSERT INTO prog_jezik VALUES

    ('1','COBOL');

    INSERT INTO prog_jezik VALUES

    ('2','Java');

  • 21

    CREATE TYPE programer_t UNDER radnik_t (

    pjezik_sifra VARCHAR(10)

    ) NOT FINAL;

    -- kreiranje FK na tablicu prog_jezik za sada ne radimo

    CREATE TABLE programer OF programer_t

    (PRIMARY KEY (sifra)) OBJECT IDENTIFIER IS PRIMARY KEY;

    Postojanje nadtablica i podtablica je ono što Date (2004, str. 882-884) smatra lošom posljedicom prve grube greške. No, moramo napomenuti da gornja varijanta nije ista kao ona koju Date navodi u knjizi (i koja je SQL standard). Naime, Oracle nema sintaksu:

    CREATE TABLE podtab UNDER nadtab

    već CREATE TABLE tablica OF podtip.

    Možemo reći kako Oracle ne poznaje pojam nadtablice i podtablice u smislu SQL standarda. Budući da Date kritizira nadtablice i podtablice, ispada da je to nepodudaranje sa SQL standardom u ovom slučaju pozitivno. Unos redaka nad prethodne dvije Oracle tablice je nezavisan - ako unesemo redak u tablicu PROGRAMERI, taj redak neće se pojaviti u tablici RADNIK, a u SQL standard varijanti hoće.

    No, Oracle na neki način ipak ima nadtablice i podtablice, ali recimo da su one implicitne – obje

    se nalaze u jednoj fizičkoj tablici. Pokušajmo nad prethodno kreiranom tablicom RADNIK napraviti sljedeće dvije INSERT naredbe:

    INSERT INTO radnik VALUES

    ('103', 'Ivo', '10');

    INSERT INTO radnik VALUES

    (programer_t ('104', 'Nina', '20', 1));

    Obje naredbe uspijevaju! Jasno je da uspijeva prva naredba, ali kako to da uspijeva i druga naredba, koja unosi programera u tablicu RADNIK? Razlog je taj što tablica RADNIK ima i (nevidljivi) stupac PROGRAMERSKI_STAZ. Naime, budući da je tablica RADNIK kreirana nad tipom RADNIK_T, čim smo napravili podtip PROGRAMER_T (iako je to bilo nakon što smo kreirali tablicu RADNIK), Oracle je tablici RADNIK automatski dodao nove stupce koji odgovaraju novim atributima koje ima podtip PROGRAMER_T (u ovom slučaju je to samo jedan atribut/ stupac):

    SELECT segcol#, name, segcollength, type#

    FROM sys.col$

    WHERE obj# =

    (SELECT object_id

    FROM user_objects

    WHERE object_name = 'RADNIK'

    )

    ORDER BY segcol#;

    SEGCOL# NAME SEGCOLLENGTH TYPE#

    ---------- ------------------------------ ------------ ----------

    0 SYS_NC_OID$ 61 23

    0 SYS_NC_ROWINFO$ 1 121

    1 SYS_NC_TYPEID$ 16 23

    2 SIFRA 10 1

    3 NAZIV 20 1

    4 ODJEL_SIFRA 10 1

    5 SYS_NC00007$ 10 1

    -- SYS_NC00007$ = pjezik_sifra

  • 22

    SELECT sifra, naziv,

    SYS_NC00007$,

    SYS_TYPEID (VALUE(r)) typeid

    FROM radnik r;

    SIFRA NAZIV SYS_NC00007 TYPEID

    ---------- -------------------- ---------- ---------------------------

    101 Ana 01

    102 Pero 01

    103 Ivo 01

    104 Nina 1 03

    -- još neki zanimljivi upiti

    SELECT VALUE (r), SYS_TYPEID (VALUE (r)) -- VALUE vraca redak kao objekt

    FROM radnik r;

    SELECT VALUE (r)

    FROM radnik r

    WHERE VALUE (r) IS OF (programer_t);

    Dakle, nismo uopće trebali kreirati tablicu PROGRAMER! No, mislimo da se Dateu ne bi sviđale niti ovakve "implicitne nadtablice i podtablice" jer i

    ovdje kreiramo (objektnu) tablicu na temelju (objektnog) tipa, što znači da i ovdje tablica ima OID, pa onda možemo kreirati reference (u drugim tablicama) na taj OID.

    Dalje, moramo primijetiti da postoji (barem) još jedan praktičan problem sa prethodnom

    objektnom tablicom RADNIK. Kad bismo npr. željeli da "implicitna podtablica PROGRAMER" (podsjećamo da ona u stvarnosti ne postoji) ima (neki) stupac koji predstavlja vanjski ključ na neku treću tablicu (npr. pretpostavimo da ima stupac PROG_JEZ_ID koji predstavlja vanjski ključ na tablicu PROGRAMSKI_JEZIK) onda taj vanjski ključ trebamo napraviti na temelju "sistemski imenovanog stupca":

    -- radi kreiranje indeksa na temelju stupca iz podtipa

    CREATE INDEX programer_jezik_fk_i ON radnik r

    (TREAT (VALUE (r) AS programer_t).pjezik_sifra);

    -- ali ne radi kreiranje FK na temelju stupca iz podtipa

    ALTER TABLE radnik r

    ADD CONSTRAINT programer_jezik_fk

    FOREIGN KEY (TREAT (VALUE (r) AS programer_t).pjezik_sifra)

    REFERENCES prog_jezik (sifra);

    ALTER TABLE radnik r

    *

    ERROR at line 1:

    ORA-01735: invalid ALTER TABLE option

    -- ne radi kreiranje FK na temelju stupca iz podtipa niti na ovaj način

    ALTER TABLE radnik

    ADD CONSTRAINT programer_jezik_fk

    FOREIGN KEY (TREAT (radnik AS programer_t).pjezik_sifra)

    REFERENCES prog_jezik (sifra);

    FOREIGN KEY (TREAT (radnik AS programer_t).pjezik_sifra)

    *

    ERROR at line 3:

    ORA-00904: : invalid identifier

  • 23

    -- ne radi kreiranje FK na temelju stupca iz podtipa niti na ovaj način

    ALTER TABLE radnik

    ADD CONSTRAINT programer_jezik_fk

    FOREIGN KEY (radnik.pjezik_sifra)

    REFERENCES prog_jezik (sifra);

    FOREIGN KEY (radnik.pjezik_sifra)

    *

    ERROR at line 3:

    ORA-00904: "RADNIK"."PJEZIK_SIFRA": invalid identifier

    -- ovako radi - kreiranje FK na temelju

    -- "sistemski imenovanog stupca" SYS_NC00007$ (= pjezik_sifra)

    ALTER TABLE radnik

    ADD CONSTRAINT programer_jezik_fk

    FOREIGN KEY (SYS_NC00007$) REFERENCES prog_jezik (sifra);

    -- DROP TABLE: programer (nije niti trebala), radnik, prog_jezik, odjel

    -- DROP TYPE: programer_t, radnik_t, prog_jezik_t, odjel

    Inače, Date navodi (2004, str. 423-424) da je jednostavno i ispravno rješenje primjera

    RADNIK-PROGRAMER (tj. primjera nadtip-podtip) moguće bez objektnih tablica. Prvo napravimo tablicu RADNIK. Zatim napravimo tablicu PROGRAMER sa dodatnim stupcima, ali i sa stupcem koji je isti kao PK tablice RADNIK i koji će istovremeno biti PK tablice PROGRAMER i FK na tablicu RADNIK. Nakon toga napravimo pogled (view) V_RADNIK_PROGRAMER kao JOIN između te dvije tablice:

    CREATE TABLE radnik (

    sifra VARCHAR(10) PRIMARY KEY,

    naziv VARCHAR2(20)

    )

    /

    CREATE TABLE programer (

    sifra VARCHAR(10) PRIMARY KEY REFERENCES radnik (sifra),

    programerski_staz NUMBER

    )

    /

    CREATE VIEW v_radnik_programer AS

    SELECT r.sifra,

    r.naziv,

    p.programerski_staz

    FROM radnik r,

    programer p

    WHERE p.sifra = r.sifra

    /

    Sada možemo raditi sljedeće: - ako želimo čitati samo radnike koji nisu programeri, radimo SELECT nad tablicom RADNIK

    - ako želimo čitati samo radnike koji jesu programeri, radimo SELECT nad pogledom

    V_RADNIK_PROGRAMER

    - ako želimo unijeti/mijenjati radnika koji nije programer, radimo INSERT/UPDATE nad tablicom RADNIK

    - ako želimo unijeti/mijenjati radnika koji je programer, radimo INSERT/UPDATE nad pogledom V_RADNIK_PROGRAMER, s tim da možemo koristiti Oracle INSTEAD OF okidač da bismo istovremeno ažurirali dvije tablice (koje čine pogled).

  • 24

    ZAKLJUČAK

    Ako gledamo SQL:1999 i SQL:2003 standarde i stanje na tržištu RDBMS sustava, možemo reći

    da objektno-relacijski DBMS (ORDBMS) sustavi u stvarnosti postoje. Međutim, možemo se složiti sa Dateom da neke objektno-orijentirane osobine koje imaju

    ORDBMS sustavi zapravo pripadaju relacijskom modelu i "običnim" RDBMS sustavima. Prije svega, misli se na mogućnost definiranja korisničkih tipova podataka, koji onda mogu poslužiti za definiranje atributa relacije.

    Date (2004, str. 891) citira Davida Maiera, poznatog stručnjaka na području objektnih baza (on je jedan od kreatora poznatog teksta "The Object-Oriented Database System Manifesto"), koji kaže: "… I think that type extensibility is the key. Identity, complex state, and encapsulation are still important, but only insomuch as they support the creation of new data types.".

    S druge strane, mogućnost da korisnički definirane tipove podataka koristimo i za definiranje "objektnih tablica", sa svim posljedicama koje to donosi (npr. posljedica je uvođenje nadtablica i podtablica), Date naziva "prva gruba greška". Uvođenje pokazivača (ili referenci, REFs) u relacijske baze Date naziva "druga gruba greška". Takve "čiste objektne osobine" trebalo bi u relacijskoj bazi (u pravilu) izbjegavati.

    Budući da se pojedinačnim elementima VARRAY tipa ne može pristupiti kroz SQL, već samo kroz PL/SQL, u Oracle bazi nije preporučljivo koristiti VARRAY tip za stupce tablice.

    Na kraju, tablice sa RVA stupcima (u Oracle terminologiji - stupci tipa ugniježđene tablice) najčešće nisu dobar dizajnerski izbor, jer sa njima model podataka sliči na nekadašnje hijerarhijske baze podataka.

  • 25

    LITERATURA:

    [1] Blaha, M. & Premerlani, W. (1998): Object-Oriented Modeling and Design for Database Applications, Prentice Hall [2] Date, C.J. (2004): An introduction to Database Systems (8.izdanje), Addison-Wesley [3] Date, C.J. (2005): Database in Depth, O'Reilly [4] Date, C.J. (2006): Date on Databases – Writings 2000-2006, Apress [5] Date, C.J. (2007): Logic and Databases – The Roots of Relational Theory, Trafford Publishing [6] De Haan, L. i Koppelaars T. (2007): Applied Mathematics for Database Professionals, Apress [7] Feuerstein S. i Pribyl B. (2005): Oracle PL/SQL Programming (4.izdanje), O'Reilly [8] Kimball, R. i Ross, M. (2002): The Data Warehouse Toolkit (2. izdanje), John Wiley & Sons [9] Kyte, T. (2003): Effective Oracle by Design, McGraw-Hill/Osborne [10] Kyte, T. (2005): Expert Oracle Database Architecture, Apress [11] Larman, C. (2002): Applying UML and Patterns (2.izdanje), Prentice Hall [12] Meyer, B. (1997): Object-Oriented Software Construction (2.izdanje), Prentice Hall [13] Radovan, M. (1993): Baza podataka: Relacijski pristup i SQL, Informator [14] Varga, M. (1994): Baze podataka: Konceptualno, logičko i fizičko modeliranje podataka, Društvo za razvoj informacijske pismenosti (DRIP) [15] Von Halle, B. (2002): Business Rules Applied: Building Better Systems Using the Business Rules Approach, John Wiley & Sons [16] Oracle priručnik 11g Release 1 (2007): Advanced Application Developer's Guide [17] Oracle priručnik 11g Release 1 (2007): Concepts [18] Oracle priručnik 11g Release 1 (2007): Object-Relational Developer's Guide [19] Oracle priručnik 11g Release 1 (2007): PL/SQL Language Reference [20] Oracle priručnik 11g Release 1 (2007): PL/SQL Packages and Types Reference [21] Oracle priručnik 11g Release 1 (2007): SQL Language Reference