<<Elöző fejezet Tartalom Minta adatok>>

7.1. Objektum orientált megközelítés
7.1.1 Öröklődés
7.2. Összetett adattípusok
7.3. Grafikus adatok tárolása
7.4. Térbeli indexelés
7.5. PostGIS

7. Újabb irányzatok az adatbáziskezelésben

Ebben a fejezetben - elsősorban a PostgreSQL adatbáziskezelő rendszer alapján - még nem standard, de egyre szélesebb körben támogatott adatbázis fejlesztéseket mutatok be, a teljesség igénye nélkül. Elsősorban a térinformatikai alkalmazás lehetőségét szem előtt tartva.

7.1 Objektumorientált megközelítés

Számos az objektum orientált megközelítés paradigmáira épülő úgynevezett objektum adatbáziskezelő rendszert (ODBMS) fejlesztettek, fejlesztenek. Az objektum orientált adatbázisokról itt találhat további cikkeket. Az SQL 1999 is objektum orientált megközelítést alkalmaz, de megtartja az SQL-92 kompatibilitást. Ezért ez az objektum modell nem felel meg az objektum orientált programnyelveknek. A relációs és az objektum orientált megközelítést egyesítő megoldásokat objektum relációs adatbáziskezelőknek (ORDBMS) nevezzük.

A relációs adatbáziskezelők többféle objektumot használnak, pl. adatbázis, tábla, index stb. Ezen objektumok közül a táblák esetén kezdenek a relációs adatbáziskezelők az objektum orientált megközelítés felé nyitni. A PostgreSQL esetén az objektum orientált megközelítéstől elvárható elzártság (encapsulation), többértelműség (polymorfizmus) és öröklés (inheritance) hármas közül az öröklődést valósították meg.

7.1.1 Öröklődés

Adatbázisainkban gyakran hasonló szerkezetű táblákat használunk, gyakran egyes táblák oszlopai között nagy az átfedés. Ezekben a táblák definiciójának egymásra építésével (örököltetésével) egyszerűbben kezelhető szerkezetet kapunk.

Egy példán keresztűl nézzük meg, hogyan alkalmazható PostgreSQL esetén az öröklődés. Az adatbázisunkban személy- és teherautó típusok adatait szeretnénk nyílvántartani. Ehhez a hagyományos megközelítés szerint a következő két táblát hoznánk létre:
Create Table szemely (
   gyarto text,
    tipus text,
    kobcenti int
);
Create Table teher (
   gyarto text,
    tipus text, 
    kobcenti int, 
    maxteher int
);

Amennyiben egy gyártó valamennyi típusát szeretnénk megkapni, függetlenül attól, hogy személy vagy teher, akkor egy unio segítségével állíthatjuk elő az eredményt.

Select tipus From szemely Where gyarto = "Opel" Union Select tipus From teher Where gyarto = "Opel";

Egy nézet tábla létrehozásával kényelmesebbé tehetjük a két tábla használatát.

Create  View jarmu As Select gyarto, tipus, kobcenti From szemely Union Select gyarto, tipus, kobcenti From teher;
Select tipus From jarmu Where gyarto = "Opel";

Ez a forma azonban az tábla aktualizálása (Update) során már nehézségeket okoz.

Ennél jobb megoldás a két tábla egymásból származtatása.

Create Table szemely (
   gyarto text,
    tipus text,
    kobcenti int
);
Create Table teher (
   maxteher int,
 ) Inherits(szemely);

A teher tábla sorai öröklik a szemely tábla oszlopait (gyarto, tipus, kobcenti). A típusokra vonatkozó lekérdezést ezután egyszerűbben leírhatjuk.

Select tipus From szemely Where gyarto = "Opel";

A fenti lekérdezés nem csak a személy táblára vonatkozik, hanem az abból származtatottakra is. Olyan lekérdezést is kiadhatunk, mely a származtatott táblákat nem veszi figyelembe.

Select tipus From Only szemely Where gyarto = "Opel";

Az "Only" kulcsszó jelzi, hogy a lekérdezés nem terjed ki a származtatott táblákra. Az Update és Delete SQL utasításokban is használható az Only kulcsszó. Az objektum orientált és hagyományos megközelítés között még nagyobb a különbség, ha többszörös származtatást használunk, például újabb járműtípusok bevezetésével (busz, motorkerékpár, stb.). Egy tábla akár több táblából származtatható, de az öröklödési fa csak hurok nélküli irányított gráf lehet.

A fenti probléma más (kevésbé elegáns, hatékony) megoldása is elképzelhető a relációs adatbázisokban.

a., Definiálhatnánk egy olyan táblát, mely tartalmazza a két tábla minden oszlopát. Személyautok esetén a "maxteher" oszlopot nem töltjük ki. Ez a megoldás egyrészt feleslegesen növeli az adatbázis méretét, másrészt pedig az oszlopok kitöltésére, üresen hagyására vonatkozó szabályrendszert kell használni (személyautók esetén nem szabad, teherautók esetén pedig kötelező kitölteni).

b., Hozzunk létre egy táblát, mely csak az egymásból származtatott táblák oszlopainak közös halmazát tartalmazza. Az alap táblából kimaradt oszlopokhoz objektum típusonként hozzunk létre egy új táblát. Ebben az esetben az új rekordok beillesztése, meglévő rekordok aktualizálása két táblára terjedhet ki, a lekérdezésekhez a két táblát össze kell kapcsolni.

7.2. Összetett adattípusok

A relációs adatbázisokban már megszoktuk, hogy az első normál forma feltétele nem mindig teljesül, például a nagy bináris objektumok (BLOB) esetén. Az objektum orientált megközelítés összetett, komplex adattípusok megvalósítását is igényli. A PostgreSQL újabb verzióban az egyes oszlopokban fix vagy változó méretű, akár több indexes tömböket is tárolhatunk. A tömb elemeinek típusa a beépített vagy a felhasználó által definiált típusok bármelyike lehet. A tömbök alkalmázára nézzük a következő példát.

Create Table fizetés (név text, havi_bér integer[]);

Az adattípus után megjelenő [] egy változó méretű tömböt jelent, a fix méretű tömböknél a méretet a zárójelek között adhatjuk meg.

A tömb típusú elemek kezelése eltér az egyszerű típusú elemekétől. Tömb feltöltése értékekkel:

INSERT INTO fizetés VALUES('Kovács', '{125000, 125000, 132000}');
INSERT INTO fizetés VALUES('Nagy', '{92000, 87000, 92000, 98000}');

Ezután nézzünk néhány lekérdezést:

SELECT név FROM fizetés WHERE havi_bér[1] > havi_bér[2];
SELECT név, havi_bér[2] FROM fizetés;
SELECT havi_bér[1:3] FROM fizetés;

Az első lekérdezés azoknak a nevét adja vissza, akiknek a második havi fizetése kisebb mint az első havi. A második lekérdezés a második havi béreket listázza. Végül a harmadik lekérdezés segítségével a tömb egy tartományát (1-3) elemét kérdezzük le. A tömb kezdő elemének indexe 1.

A tömb elemek módosítása vonatkozhat a teljes tömbre vagy annak csak egy részére, de a tömb indexeinek folytonosnak kell lennie, nem maradhatnak ki indexek.

UPDATE fizetés SET havi_bér = '{140000, 150000}' WHERE név='Kovács';
UPDATE fizetés SET havi_bér[3] = 145000 WHERE név='Kovács;
UPDATE fizetés SET havi_bér[3:4] = '{145000, 155000}';

Az első példa a teljes tömbelem tartalmát lecseréli. A második példában egy elemmel bővítettük a tömböt. A harmadik példában a tömb egy tartományt aktualizáltuk.

Fix méretű tömbök esetén a tábla definicióban a tömb maximális méretét adhatjuk meg a "[" "]" jelek között. Jelenleg a Postgres nem korlátozza a fix méretű tömbök indexeit sem, így a változó méretű (dinamikus) tömbökkel azonos módon használható. Több indexes tömbök is használhatók. A tömbök méretét az array_dims függvénnyel kérdezhetjük le.

SELECT array_dims(havi_bér) FROM fizetés;

A tömbök fenti módon bemutatott használata az első normál forma szabályát sérti. A normalizált, két táblára bontott megoldás egyszerűbben kezelhető (pl. keresés). A grafikus adatok, koordinátalisták tárolására viszont hatékonyan használhatók a tömbök.

Az egyes tömbelemek nem vehetik fel a NULL értéket, de az egész tömb igen.

7.3. Grafikus adatok tárolása

Egyre több relációs adatbáziskezelő (Oracle Spatial Cartridge, PostgreSQL, MySQL, stb.) teszi lehetővé a grafikus elemek koordinátáinak tárolását és térbeli indexelését. Ezeket azonban nem a normalizált formában tárolják, hanem inkább változó hosszúságú rekordokat=tömböket használnak. Erre elsősorban a hatékony grafikus megjelenítés miatt van szükség.

Normalizált törtvonal tárolás Változó hosszúságú rekord
Pontok
pont_id x y
1 12 23
...    
Törtvonalak
vonal_id sorszam pont_id
1 1 1
...    

Egy törtvonal lekérdezése:

Select x,y From Pontok, Törtvonalak 
    Where Pontok.pont_id = Törtvonalak.pont_id   and vonal_id = 1
    Order By sorszam;
Törtvonalak
vonal_id x1 y1 x2 y2 x3 y3 ... ...
1 12 23 ...          
...                

Egy törtvonal lekérdezése:

Select * From Törtvonalak Where vonal_id  = 1;

A PostgreSQL a tömb típusú mezők segítségével valósítja meg a grafikus adatok tárolását. A következő speciális adattípusokat használhatjuk térképi 2D-s grafikus elemek tárolására.

Grafikus elem Méret (Byte) Megjelenés Megjegyzés
pont (point) 16 (x,y) Pont elem
egyenes (line) 32 ((x1,y1),(x2,y2)) Végtelen egyenes
szakasz (lseg) 32 ((x1,y1),(x2,y2)) Véges vonalszakasz
téglalap (box) 32 ((x1,y1),(x2,y2)) Koordinátatengelyekkel párhuzamos téglalap
zárt törtvonal (path) 16+16n ((x1,y1),...) Zárt törtvonal (poligonnal azonos)
nyitott törtvonal (path) 16+16n [(x1,y1),...] Nyitott törtvonal
poligon (polygon) 40+16n ((x1,y1),...) Poligon (zárt törtvonallal azonos)
kör (circle) 24 <(x,y),r> Kör, középpont, sugár

A PostgreSQL a "Simple Features for SQL" szabványt követi, melyet az OpenGIS Consortium dolgozott ki. A szabvány fő jellemzői

A Postgres számos geometriai operátort definiál, melyeket az alábbi táblázat tartalmaz.

>
Operátor Leírás Példa Eredmény
+ Eltolás SELECT box '((0,0),(1,1))' + point '(2.0,0)'; (3,1),(2,0)
- Eltolás SELECT box '((0,0),(1,1))' - point '(2.0,0)'; (-1,1),(-2,0)
* Skálázás, forgatás SELECT box '((0,0),(1,1))' * point '(2.0,0)'; (2,2),(0,0)
/ Skálázás, forgatás SELECT box '((0,0),(2,2))' / point '(2.0,0)'; (1,1),(0,0)
# Metszéspont SELECT lseg '((1,-1),(-1,1))' # lseg '((1,1),(-1,-1))'; (0,0)
# Pontok száma (path vagy polygon) SELECT # path '((1,1),(3,2),(4,0))'; 3
## Elem legközelebbi pontja SELECT point '(0,0)' ## lseg '((2,0),(0,2))' (1,1)
&& Átfedés? SELECT box '((0,0),(5,5))' && box '((4,4),(7,7))' t (igaz)
&< Átfedés balra? SELECT box '((0,0),(1,1))' &< box '((0,0),(2,2))' t (igaz)
&> Átfedés jobbra? SELECT box '((0,0),(3,3))' &> box '((0,0),(2,2))' t (igaz)
<-> Távolság SELECT circle '((0,0),1)' <-> circle '((5,0),1)' 3
<< Balra? SELECT circle '((0,0),1)' << circle '((5,0),1)' t (igaz)
<^ Alatta? SELECT circle '((0,0),1)' <^ circle '((0,5),1)' t (igaz)
>> Jobbra? SELECT circle '((0,0),1)' >> circle '((5,0),1)' f (hamis)
>^ Felette? SELECT circle '((0,0),1)' >^ circle '((0,5),1)' f (hamis)
?# Metszés vagy átfedés? SELECT lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))' t (igaz)
?- Vízszintes? SELECT point '(1,0)' ?- point '(0,0)' t (igaz)
?-| Merőleges? SELECT lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))' t (igaz)
@-@ Hossz vagy kerület SELECT @-@ path '((0,0),(2,0),(2,2),(0,2))' 8
?| Függőleges? SELECT point '(0,1)' ?| point '(0,0)' t (igaz)
?|| Párhuzamos? SELECT lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))' t (igaz)
@ Tartalmaz vagy rajta? SELECT point '(1,1)' @ circle '((0,0),2)' t (igaz)
@@ Középpont SELECT @@ circle '((0,0),10)' (0,0)
~= Azonos? SELECT polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))' t (igaz)

Az operátorok mellett a geometriai elemekhez számos függvény is kapcsolódik. Ezeket az alábbi táblázat foglalja össze.

Függvény Visszaadott érték Leírás Példa Eredmény
area(objektum) duplapontos (double) az objektum területe area(box '((0,0),(1,1))') 1
box(box,box) téglalap (box) téglalapok közös része box(box '((0,0),(1,1))',box '((0.5,0.5),(2,2))')  
center(objektum) pont (point) az objektum középpontja center(box '((0,0),(1,2))') (0.5,1)
diameter(circle) duplapontos (double) kör átmérője diameter(circle '((0,0),2.0)') 4
height(box) duplapontos (double) téglalap magassága height(box '((0,0),(1,1))') 1
isclosed(path) logikai (bolean) zárt törtvonal? isclosed(path '((0,0),(1,1),(2,0))') t (igaz)
isopen(path) logikai (bolean) nyitott törtvonal? isopen(path '[(0,0),(1,1),(2,0)]') t (igaz)
length(object) duplapontos (double) az objektum hossza length(path '((-1,0),(1,0))') 4
npoints(path) egész (integer) pontok száma npoints(path '[(0,0),(1,1),(2,0)]') 3
npoints(polygon) egész (integer) pontok száma npoints(polygon '((1,1),(0,0),(1,0))') 3
pclose(path) zárt törtvonal (path) törvonal zárt törtvonallá konvetálása pclose(path '[(0,0),(1,1),(2,0)]') ((0,0),(1,1),(2,0))
popen(path) nyitott törtvonal (path) törtvonal nyitott törtvonallá konvertálása popen(path '((0,0),(1,1),(2,0))') [(0,0),(1,1),(2,0)]
radius(circle) duplapontos (double) kör sugara radius(circle '((0,0),2.0)') 2
width(box) duplapontos (double) téglalap szélessége width(box '((0,0),(1,1))') 1

A különböző geometriai elemre több típus konverzió függvény is létezik. ezeket az alábbi táblázat foglalja össze.
Függvény Visszaadott érték Leírás Példa Eredmény
box(circle) téglalap (box) körbe illesztett téglalap box(circle '((0,0),2.0)') (1.41,1.41),(-1.41,-1.41)
box(point,point) téglalap (box) téglalap két átellenes pontból box(point '(0,0)', point '(1,1)') (1,1),(0,0)
box(polygon) téglalap (box) polygon befoglaló téglalapja box(polygon '((0,0),(1,1),(2,0))') (2,1),(0,0)
circle(box) kör (circle) téglalapba illesztett kör circle(box '((0,0),(1,1))') <(0.5,0.5),0.71>
circle(point, double precision) kör (circle) pont és sugár alapján kör circle(point '(0,0)', 2.0) <(0,0),2>
lseg(box) szakasz (lseg) téglalap átlója lseg(box '((-1,0),(1,0))') [(1,0),(-1,0)]
lseg(point, point) szakasz (lseg) pontokat összekötő szakasz lseg(point '(-1,0)', point '(1,0)') [(-1,0),(1,0)]
path(polygon) törtvonal (path) poligon átalakítás törtvonallá path(polygon '((0,0),(1,1),(2,0))') ((0,0),(1,1),(2,0))
point(circle) pont (point) kör középpontja point(circle '((0,0),2.0)') (0,0)
point(lseg, lseg) pont (point) metszéspont point(lseg '((-1,0),(1,0))', lseg '((-2,-2),(2,2))')  
polygon(box) poligon (polygon) téglalapból poligon polygon(box '((0,0),(1,1))') ((0,0),(0,1),(1,1),(1,0))
polygon(circle) poligon (polygon) körből 12 pontból álló poligon polygon(circle '((0,0),2.0)') ((-2,0),(-1.7,1.0),(-1.0,1.7),(0.,2),(1.0,1.7),(1.7,1.0),(2,0.0),(1.7,-1.0),(1.0,-1.7),(0.0,-2),(-1.0,-1.7),(-1.7,-1.0))
polygon(n, circle) poligon (polygon) körből n pontból álló poligon polygon(12, circle '((0,0),2.0)') ((-2,0),(-1.7,1.0),(-1.0,1.7),(0.,2),(1.0,1.7),(1.7,1.0),(2,0.0),(1.7,-1.0),(1.0,-1.7),(0.0,-2),(-1.0,-1.7),(-1.7,-1.0))
polygon(path) poligon (polygon) törtvonalból poligon polygon(path '((0,0),(1,1),(2,0))') ((0,0),(1,1),(2,0))

A térinformatikai adatok relációs adatbázisban tárolásához egy önálló modult is készítettek a Postgres objektum relációs adatbáziskezelőhöz. Ez a PostGIS modul. A PostGIS modul relációs táblákba tudja konvertálni az elterjedtebb térinformatikai adatformátumokat, többféle vetületet kezel és térkép megjelenító programokkal (pl. Mapserver) biztosítja a kapcsolatot.

7.4. Térbeli indexelés

...

7.5. PostGIS

A PostGIS a PostgreSQL adatbáziskezelő térinformatikai alkalmazásához tovább bővített változata. Az Oracle Spatial Cartridge vagy ESRI ARCSDE téradatszervereknek megfelelő funkcionalítást biztosít a nyíltforrású ingyenes (GPL) szoftverek körében.
<<Elöző fejezet Tartalom Minta adatok>>