User Defined Type (UDT) adattípusok az Oracle 10g-ben ----------------------------------------------------- Kollekció: ---------- Dinamikus tömb (VARRAY) ======================= CREATE OR REPLACE TYPE cimlista_var AS VARRAY(5) OF VARCHAR2(20); CREATE TABLE kolcsonzes2(nev VARCHAR2(20), datum date, konyvek cimlista_var); INSERT INTO kolcsonzes2 VALUES('Bolcs Leo', to_date('2007-11-01', 'yyyy-mm-dd'), cimlista_var('Biblia', 'Talmud', 'Mahabharata', 'Odusszeia')); INSERT INTO kolcsonzes2 VALUES('Okos Akos', to_date('2007-11-02', 'yyyy-mm-dd'), cimlista_var('Rokonok', 'Fekete Gyemantok')); A maximális elemszámot később módosíthatjuk: ALTER TYPE ... MODIFY LIMIT SELECT konyvek FROM kolcsonzes2 WHERE nev like 'Okos%'; KONYVEK ------------------------------------------- CIMLISTA_VAR('Rokonok', 'Fekete Gyemantok') A lekérdezés eredménye is dinamikus tömb lesz. A TABLE függvénnyel táblává is alakíthatjuk a tömböt: SELECT * FROM TABLE(SELECT konyvek FROM kolcsonzes2 k WHERE nev like 'Okos%'); COLUMN_VALUE ----------------- Rokonok Fekete Gyemantok Ha a dinamikus tömböt táblaként szeretnénk használni, mint az iménti lekérdezésben, akkor valahogy hivatkoznunk kell annak oszlopára. Ha objektumokból állna a dinamikus tömb (lásd lejjebb), akkor nincs probléma, hiszen az objektumnak vannak attribútumai, és ezek nevét használhatjuk. Ha viszont egyszerű típusú elemekből áll a tömb, akkor nincs oszlopnév. Ilyenkor használható a COLUMN_VALUE. SELECT nev, datum, t.column_value FROM kolcsonzes2 k, TABLE(k.konyvek) t; NEV DATUM COLUMN_VALUE -------------------- ---------- ---------------- Bolcs Leo 2007-11-01 Biblia Bolcs Leo 2007-11-01 Talmud Bolcs Leo 2007-11-01 Mahabharata Bolcs Leo 2007-11-01 Odusszeia Okos Akos 2007-11-02 Rokonok Okos Akos 2007-11-02 Fekete Gyemantok Nem kell WHERE feltétel, anélkül is csak a megfelelő párosítások lesznek az eredményben. PL/SQL-ben ciklusban is feldolgozható a dinamikus tömb, hasonlóan a plsql-beli tömbhöz (TABLE OF). A plsql-beli TABLE OF egy plsql nyelvben használható tömb típus, a VARRAY (és a későbbi NESTED TABLE) ezzel szemben SQL nyelv-beli típus, vagyis plsql-en kívül is használható. LIMIT -> maximális elemszám COUNT -> aktuális elemszám (FIRST, LAST, NEXT(i) ...stb.) NULL is lehet az elemek közt: INSERT INTO kolcsonzes2 VALUES('Fura Feri', to_date('2007-11-03', 'yyyy-mm-dd'), cimlista_var('Zabhegyezo', NULL, 'Szeretetkonyv')); BEGIN FOR rec IN (SELECT * FROM kolcsonzes2) LOOP dbms_output.put_line(rec.nev||' -> könyvek: '||rec.konyvek.COUNT||'/'||rec.konyvek.LIMIT); FOR i IN 1..rec.konyvek.COUNT LOOP dbms_output.put_line(TO_CHAR(i, '999')||' '||rec.konyvek(i)); END LOOP; END LOOP; END; Bolcs Leo -> könyvek: 4/5 1 Biblia 2 Talmud 3 Mahabharata 4 Odusszeia Okos Akos -> könyvek: 2/5 1 Rokonok 2 Fekete Gyemantok Fura Feri -> könyvek: 3/5 1 Zabhegyezo 2 3 Szeretetkonyv Bonyolultabb eleme is lehet a tömbnek, pl. objektum: CREATE OR REPLACE TYPE szemely_lista_var AS VARRAY(10) OF szemely_typ; CREATE TABLE csapat(nev VARCHAR2(10), tagok szemely_lista_var); INSERT INTO csapat VALUES('Fradi', szemely_lista_var(szemely_typ('Albert Flori', cim_typ('Kicsi', 'Bp', 'Magyar', 1234)), szemely_typ('Novak Dezso', cim_typ('Nagy', 'Vac', 'Magyar', 4321)) ) ); INSERT INTO csapat VALUES('Ujpest', szemely_lista_var(szemely_typ('Bene Ferenc', cim_typ('Lakatos', 'Tata', 'Magyar', 1234)), szemely_typ('Fazekas LAszlo', cim_typ('Tatai', 'Bp', 'Magyar', 4321)) ) ); Nézzünk néhány lekérdezést arra, hogy hogyan férhetünk hozzá az egyes részekhez. SELECT tagok FROM csapat cs WHERE nev='Fradi'; -- 1 dinamikus tömböt kapunk vissza TAGOK(NEV, CIM(UTCA, VAROS, ORSZAG, IRSZAM)) ------------------------------------------------------------------------------------- SZEMELY_LISTA_VAR(SZEMELY_TYP('Albert Flori', CIM_TYP('Kicsi', 'Bp', 'Magyar', 1234)), SZEMELY_TYP('Novak Dezso', CIM_TYP('Nagy', 'Vac', 'Magyar', 4321))) SELECT nev, cim FROM TABLE(SELECT tagok FROM csapat cs WHERE nev='Fradi'); -- a dinamikus tömb elemeit kapjuk vissza külön sorokban NEV CIM(UTCA, VAROS, ORSZAG, IRSZAM) ----------------------------------------------------- Albert Flori CIM_TYP('Kicsi', 'Bp', 'Magyar', 1234) Novak Dezso CIM_TYP('Nagy', 'Vac', 'Magyar', 4321) Adjuk meg egy csapat tagjainak nevét: SELECT nev FROM TABLE(SELECT tagok FROM csapat cs WHERE nev='Fradi'); NEV ------------ Albert Flori Novak Dezso Adjuk meg egy csapat tagjainak városait (a címükből kivéve) SELECT t1.cim.varos FROM TABLE(SELECT tagok FROM csapat cs WHERE nev='Fradi') t1; CIM.VAROS --------- Bp Vac Adjuk meg egy csapat tagjainak nevét és városát SELECT nev, t1.cim.varos FROM TABLE(SELECT tagok FROM csapat cs WHERE nev='Fradi') t1; -- A nev előtt nem kötelező a minősítés (t1.nev), de oda is írhatjuk. NEV CIM.VAROS ---------------------------------------- ---------- Albert Flori Bp Novak Dezso Vac SELECT cs.nev, t.nev FROM csapat cs, TABLE(cs.tagok) t; NEV NEV ---------- --------------- Fradi Albert Flori Fradi Novak Dezso Ujpest Bene Ferenc Ujpest Fazekas LAszlo Információk a katalógusból: DBA_COLL_TYPES, DBA_VARRAYS SELECT column_name, data_type, data_type_owner FROM user_tab_columns WHERE table_name='CSAPAT'; COLUMN_NAME DATA_TYPE DATA_TYPE_OWNER ------------------------------ -------------------- --------------- NEV VARCHAR2 TAGOK SZEMELY_LISTA_VAR NIKOVITS SELECT owner, object_type FROM dba_objects WHERE object_name='SZEMELY_LISTA_VAR'; SELECT typecode, attributes FROM dba_types WHERE type_name='SZEMELY_LISTA_VAR'; TYPECODE ATTRIBUTES ------------------------------ ---------- COLLECTION 0 Ebből látszik, hogy kollekció, ezért most itt keresünk tovább -> DBA_COLL_TYPES SELECT coll_type, upper_bound, elem_type_name, elem_type_owner FROM dba_coll_types WHERE type_name='SZEMELY_LISTA_VAR'; COLL_TYPE UPPER_BOUND ELEM_TYPE_NAME ELEM_TYPE_OWNER ----------------- ----------- ------------------------ --------------- VARYING ARRAY 10 SZEMELY_TYP NIKOVITS És innen a már megismert módon haladuk tovább.