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(
'
]>
'));