XML típus az oracle-ben ----------------------- Az XML (Extensible Markup Language) dokumentumok leírására szolgáló nyelv. Egy XML dokumentum egy irányított cimkézett gráffal reprezentálható. Jól formázott egy dokumentum ha: - egyetlen gyökéreleme van - az elemeket nyitó és záró tag-ek veszik körül: ... - minden (nem gyökér) elememet pontosan egy másik tatalmaz, átfedés nincs Egy dokumentum érvényes, ha megfelel egy adott sémának. A sémák leírására használatos nyelvek: DTD XSDL Nézzük meg, hogy az Oracle-ben hogyan van létrehozva és tárolva az XMLTYPE típus. SELECT owner, object_type FROM dba_objects WHERE object_name ='XMLTYPE'; OWNER OBJECT_TYPE ------------------------------ ------------ SYS TYPE SYS TYPE BODY PUBLIC SYNONYM A fentiekből látható, hogy valójában egy objektum-típusként jelenik meg az XMLTYPE. És mivel létre van hozva publikus szinonima, ezért az alábbi példákban a SYS.XMLTYPE helyett írhatunk egyszerűen csak XMLTYPE-ot. SELECT typecode, attributes, methods FROM dba_types WHERE type_name='XMLTYPE'; TYPECODE ATTRIBUTES METHODS ------------------------------ ---------- ---------- XMLTYPE 0 40 40 metódus van létrehozva hozzá, amelyek közül van amelyik túlterhelt. A metódusok paraméterei és visszatérési értékei lekérdezhetők táblázatos formában: SELECT * FROM dba_type_attrs WHERE type_name='XMLTYPE'; SELECT * FROM dba_type_methods WHERE type_name='XMLTYPE'; SELECT * FROM dba_method_params WHERE type_name='XMLTYPE'; SELECT * FROM dba_method_results WHERE type_name='XMLTYPE'; Vagy az összes információ egy forráskód jellegű formában: SELECT text FROM dba_type_versions WHERE type_name='XMLTYPE' order by line; (A fenti lekérdezés eredményét tettem bele az XmlType.sql állományba.) A példaadatbázis egyik táblájának létrehozása (oe.warehouses mintájára) CREATE TABLE raktar ( raktar_azon NUMBER(3), raktar_spec SYS.XMLTYPE, raktar_nev VARCHAR2(35 BYTE), epulet_azon NUMBER(4) ); Beszúrás a táblába: INSERT INTO raktar VALUES(1, SYS.XMLType.CreateXML( ' Sajat 25000 Igen Nem Utca '), 'raktar1', '1000'); INSERT INTO raktar VALUES(2, SYS.XMLType.CreateXML( ' Berelt 20000 Nem Nem Garazs '), 'raktar2', '2000'); Lekérdezés: Amikor XML adatot kérdezünk le, a különböző kliens programok különbözőképpen írják ki az eredményt. A régebbi verziójú programok vagy ki sem írják, vagy csak annyit írnak ki, hogy ADT (Abstract Data Type). A megfelelő tagfüggvényekkel Stringgé vagy CLOB-bá alakíthatjuk, és akkor már kiírják. De a fa szerkezetet legkényelmesebben egy SQLPLUS programmal kaphatjuk meg, ami pl. a pandora gépen van telepítve. (putty -> pandora majd sqlplus @oradb) Egy másik lehetőség, hogy az SQLDeveloperből nem az aktuális utasítást futtatjuk (Execute Statement), hanem úgy futtatunk akár egyetlen kijelölt utasítást, mint egy sql scriptet (Run Script). Ilyenkor a kliens program úgy viselkedik, mintha egy sqlplus program lenne és szebben írja ki a fa szerkezetet. Formázott kiírás (Pretty-Printing) Általában jelentősen lassítja a feldolgozást, ha a fa szerkezetnek megfelelően írja ki az eredményt az Oracle, ezért alapértelmezés szerint nem is így írja ki a lekérdezések eredményét. Ha az EXTRACT tagfüggvényt (MEMBER) használjuk, akkor mindig formázva írja ki, így kisebb méretű dokumentumokra ezt érdemes használni. Fontos a kisbetű/nagybetű megkülönböztetése. Ha kisbetűvel írnánk pl. a 'tulaj'-t, akkor nem adna vissza semmit. (a korrelációs változó használata is kötelező) COLUMN Eredmeny FORMAT A50 SELECT r.raktar_azon, r.raktar_spec.EXTRACT('/Raktar/Tulaj') Eredmeny FROM raktar r; RAKTAR_AZON EREDMENY ----------- -------------------------------------------------- 1 Sajat 2 Berelt A fenti lekérdezés eredményének 2. oszlopa is egy XMLTYPE typusú érték, vagyis egy jól formált XML dokumentum. Az eredményt be lehetne pl. szúrni a következő táblába. CREATE TABLE tempXML (azon NUMBER(4), o sys.xmltype); Egy XML dokumentumot karakter típusú adattá konvertálhatunk a getStringVal tagfüggvénnyel: (vagy CLOB-bá a getCLobVal függvénnyel) SELECT r.raktar_azon, r.raktar_spec.EXTRACT('/Raktar/Terulet').getStringval() "Eredmeny" FROM raktar r WHERE r.raktar_azon=1 RAKTAR_AZON Eredmeny ----------- -------------------------------------------------- 1 25000 Az iménti lekérdezés eredménye már karakter típusú. Ennek ellenére ezt a sort is be lehet szúrni az előző táblába, mivel a jól formált dokumentumot tartalmazo stringet az oracle automatikusan konvertálja. Ha a nyitó és záró tag-ekre nincs szükségünk, magát a tartamát is megkaphatjuk a csomópontnak a text() függvény segítségével. Ha numerikus érték a tartalom, akkor is ezzel a függvénnyel kell kiszednünk, legfeljebb még konvertálnunk kell majd. Az ilyen eredmény viszont már nem lesz jól formált XML dokumentum. Az alábbi lekérdezésnek a 2. oszlopa úgynevezett XML dokumentumtöredék (nem XMLType és nem is karakteres adat) Ennek eredményét nem lehet beszúrni a tempXML táblába, mivel az nem jól formált XML. XMLType oszlopba csak jól formált dokumentumot lehet beszúrni !!! SELECT r.raktar_azon, r.raktar_spec.EXTRACT('/Raktar/Tulaj/text()') "Eredmeny" FROM raktar r; RAKTAR_AZON Eredmeny ----------- -------------------------------------------------- 1 Sajat 2 Berelt Az így kinyert dokumentumtöredék részben mégis úgy viselkedik mintha XML dokumentum lenne, mivel meg lehet rá hívni a típus tagfüggvényeit (getStringVal, getNumberVal). Az alábbi lekérdezés eredménye hagyományos karakter illetve numerikus adat. SELECT r.raktar_azon, r.raktar_spec.extract('/Raktar/Tulaj/text()').getStringval() "Eredmeny", r.raktar_spec.extract('/Raktar/Terulet/text()').getNumberval() "Eredmeny2" FROM raktar r WHERE r.raktar_azon=1; RAKTAR_AZON Eredmeny Eredmeny2 ----------- ------------------- ---------- 1 Sajat 25000 A dokumentumtöredékekből különböző függvényekkel (pl. SYS_XMLGEN) lehet majd jól formált XML-t létrehozni. Másik tábla kicsit több adattal: CREATE TABLE kolcsonzes(azon NUMBER(4), kolcs_spec SYS.XMLType); INSERT INTO kolcsonzes VALUES(1, SYS.XMLType.CreateXML( ' 2000 2500 Szep Holnap 3000 Jegkorszak Best Of 2000 Igy alakult 3200 Shrek Uvegtigris ')); XML sorobjektum --------------- A fenti táblában az XML típus oszlopobjektumként szerepel, de lehetne sorobjektum is, például az alábbi módon. CREATE TABLE kolcsonzes_xmlt OF XMLType; INSERT INTO kolcsonzes_xmlt SELECT kolcs_spec FROM kolcsonzes k WHERE azon=1; Mivel ez is lényegében egy objektum, ezért erre is a korábban megismert módon hivatkozhatunk. SELECT object_value FROM kolcsonzes_xmlt; OBJECT_VALUE ---------------------------------- ... Vagy a fentivel ekvivalens alábbi módon: SELECT VALUE(k) FROM kolcsonzes_xmlt k; VALUE(k) ---------------------------------- ... A sorobjektumnak most is van objektum azonosítója, amit lekérdezhetünk vagy beszúrhatunk egy táblába, majd a DEREF függvény segítségével lekérdezhetjük az objektumot. Vagy akár egy XPath lekérdezést is megfogalmazhatunk rá, mivel az egy XMLTYPE típusú érték. SELECT REF(t) FROM kolcsonzes_xmlt t; CREATE TABLE xmlt_ref AS SELECT 1 AS azon, REF(t) AS xmldoku FROM kolcsonzes_xmlt t; SELECT DEREF(xmldoku) FROM xmlt_ref; DEREF(xmldoku ---------------------------------- ... SELECT DEREF(xmldoku).EXTRACT('//Kolcsonzo[@nev="Gipsz Jakab"]//CD') FROM xmlt_ref; ------------------------ Szep Holnap 3000 Érvényes dokumentum megadása DTD-vel együtt ------------------------------------------- INSERT INTO kolcsonzes VALUES(3, SYS.XMLType.CreateXML( ' ]> ')); SELECT k.kolcs_spec.EXTRACT('/') FROM kolcsonzes k WHERE azon=3; ------------------------------------------ Vegyes tartalmú elem, és annak DTD-je: INSERT INTO kolcsonzes VALUES(4, SYS.XMLType.CreateXML( ' ]> Szeretem az görögdinnyét nagyon ')); INSERT INTO kolcsonzes VALUES(5, SYS.XMLType.CreateXML( ' ]> 2000 Uvegtigris ')); INSERT INTO kolcsonzes VALUES(6, SYS.XMLType.CreateXML( ' ]> '));