2011. június 12.

Python és az SQLite – adatbázis, lájtosan

Előbb vagy utóbb eljön az a pillanat, amikor az ember úgy érzi: az addig értelmes és szép adathalmaz túl nagyra hízott, kaotikus, átláthatatlan, kezelhetetlen és lassú. Igen, ilyenkor kell egy adatbázis. A Python programozásban az a szép, hogy egyszerű mégis elegáns, és szerencsére a beépített adatbázis-modulja is ilyen: a SQLite a széleskörben elterjedt SQL szabványon nyugvó relációs adatbázisok kistestvére. Használata hasonlít hozzájuk, viszont kellemes előnye, hogy nincs szükség külön adatbázis-szerverre (az SQLite egyébként egy C-könyvtár, és nem csak a python használja; a szinte szabványos SQL szintaxis miatt a későbbi esetleges váltás nagyobb adatbázisokra sem túl fájdalmas).



Tehát, a probléma: szótárt írunk, de túl sok a szó (közismert, ugye, hogy 10.000 szó az még kutyafüle, 30.000 szónál kezdődik egy tisztességes középszótár, a határ pedig a csillagos ég). Azt kellene megcsinálni, hogy gyorsan kereshető legyen a szótárunk, természetesen mindkét irányból, vagyis: magyar szóra a cseh megfelelőjét, cseh szóra a magyar párját várjuk.

Létezik egyébként a Python-ban is egy ún. dictionary-típus, ami egy olyan tömb, amiben az indexek számok helyett szavak (sztringek). Ez nem is olyan rossz ötlet, de nem oldja meg a kétoldalú keresés problémáját (ehhez ugyanis előbb “invertálni” kellene, ami egyáltalán nem biztos, hogy sikerül), illetve a szinonimák kérdése is problémás – tudjuk ugyanis, hogy egy index-hez csak egy érték tartozhat. A memória-kérdésekről nem is beszélünk.

Akarunk tehát egy adatbázist. Az SQLite ezt egy külön fájlban tárolja (hiszen nincs szerver), ami ismét csak jó, mert szabadon lehet másolni, exportálni-importálni (excelbe, például). Következzék egy kódrészlet:






Itt a szavak tömbben tároljuk a szavainkat (figyeljük, hogy van két egyforma alak is!). Létrehozunk egy conn nevű változót, amivel csatlakozunk egy adatbázishoz (ez lesz a file neve, vagyis db.sqlite). Ezt a csatlakozást nyilvánvalóan le is kell majd zárnunk (kód vége), miután a .commit() metódussal érvényesítettük az adatbázison végrehajtott műveleteket. Ez azért fontos, mert amíg ezt nem tesszük meg, a változásokat nem menti az SQLite.

A csatlakozás után létrehozunk egy ún. kurzort, (curs változó) a conn.cursor() metódussal. Ennek a curs nevű változónak a curs.execute() metódusával tudunk kommunikálni az adatbázissal. Gyakorlatilag úgy működik, mint egy fájl: írhatunk bele és olvashatunk belőle. Íráskor már az SQLite szintaxisát kell használnunk.

A következő parancs – nem lesz nehéz kitalálni – egy táblát csinál. Egy adatbázisban több tábla is lehet, és egy táblát csak egyszer lehet létrehozni. A táblában oszlopok vannak, minden oszlopnak van neve és típusa. A szótárunkban tehát minden bejegyzésnek (szónak) lesz egy azonosítója (id), és egy magyar illetve cseh névre hallgató szöveg típusú mezője. Itt tároljuk a megfelelő alakokat. Az id ún. kulcs, ez biztosítja a rekord egyediségét – az AUTOINCREMENT
paraméter erről gondoskodik, nekünk ezzel nem kell foglalkoznunk. Egyszóval, minden bejegyzésnek, még ha azonos szavakról is van szó, egyedi azonosítója lesz.

CREATE TABLE szavak (id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, magyar TEXT, cseh TEXT)

A kód következő részében, amely a szavak beírásáról gondoskodik, ezt látjuk:


INSERT INTO szavak (magyar, cseh) VALUES (?, ?)


Ez a rész beilleszti a szavak nevű tábla két megadott mezőjébe a megadott értékeket. Ezeket megadhatnánk a parancson belül is, de a kérdőjelek helyére az .execute metódus beilleszti azokat – így egyszerűbb és biztonságosabb. Érdemes megemlíteni, hogy az SQLite unicode szöveget vár, ezért ha pl. UTF-8 van a rendszerünkön, akkor azokat először át kell konvertálni (.decode metódus).

Létrehoztunk tehát egy adatbázist, de ez lekérdezések nélkül még semmire sem jó.




A lekérdezésekhez ugyanúgy csatlakoznunk kell az adatbázishoz, azonban lezáráskor a .commit() metódusra nincs szükség, ha változásokat nem eszközöltünk. A .execute metódussal a következő parancsot adjuk ki:

SELECT id,magyar FROM szavak WHERE cseh=?

Ezzel kiválasztjuk mindazokat a mezőket (id, magyar)a megadott táblából (szavak) , amelyek megfelelnek a feltételnek (a cseh mező értéke megegyezik azzal a szóval, amelyet keresünk). Az eredményeket a curs.fetchall() metódusában kapjuk meg. Ez, a fentiekben elmondottak miatt nem biztos, hogy csak egy érték lesz, ezért tömbböt kapunk vissza; és mivel nem feltétlenül csak egy mező értékét kérdeztük le, a tömb elemei listák lesznek. Ezért egy ciklussal írjuk ki végül az eredményeket.

Az fentiek segítségével több ezer adatból álló adathalmazokat rendezhetünk úgy, hogy jól átlátható és egyszerűen kereshető legyen. Az SQLite további lehetőségeiről (hisz az írás/lekérdezésnél ezerszer többre képes) egy következő postban, addig is érdemes lehet megnézni ezt az érthetően megírt tutorialt illetve a python dokumentációjának ide vonatkozó részeit.



Nincsenek megjegyzések: