
A példaprogram használata előtt létre kell hozni egy SOUSER sémát az Oracle adatbázis-rendszerünkben, és fel kell ruházni DBA jogosultsággal. A sémába bejelentkezve le kell futtatni a mellékelt Oracle02.sql script-et a megfelelő objektum létrehozásához.
PL/SQL
Előző cikkünkben csak említés szintjén találkozhattunk a PL/SQL kifejezéssel, most azonban bővebb magyarázattal szolgálunk. Ahhoz ugyanis, hogy komolyan munkához láthassunk az Oracle rendszerben, meg kell ismernünk a rendszer belső nyelvét. A PL/SQL, mint belső nyelv lehetővé teszi, hogy blokk struktúrájú procedurális kódrészletekben adatmanipulációs és lekérdező utasításokat hajtsunk végre. Hatékonyan támogatja tranzakció-kezelési feladatok megoldását.
Struktúrája a következő:
Ezen jellemzője révén a PL/SQL–ben a programok logikai részekre oszlanak, melyekhez utasítások és az adott blokkban használható (lokális) változók tartoznak. Ezen túlmenően a blokk lehetővé teszi a blokkon belül bekövetkezett hibaállapotok (kivételek) kezelését.
Használhatunk feltételes utasításokat, hurkokat és elágazásokat a program lefolyásának vezérlésére, és annak eldöntésére, hogy mikor és hogyan kell SQL vagy más utasításokat végrehajtani. Az Oracle eszközei az utasítások együttesét így csoportosan értelmezik, és nem kell minden parancsot külön trigger lépésekbe tennünk, illetve nem kell minden SQL utasítást külső programnyelvbe ágyaznunk.
A PL/SQL központi szerepet játszik az Oracle szerverben a tárolt eljárások, triggerek és csomagok létrehozásakor. Változói és adattípusai megfelelnek az SQL adattípusainak.
A PL/SQL nem önálló Oracle termék, hanem egy programnyelv és a hozzá tartozó fordító és futtató rendszer, melyet az Oracle szerver és bizonyos Oracle eszközök alkalmaznak. A PL/SQL blokkokat az ún. „PL/SQL gépek” hajtják végre, melyek részei az Oracle szervernek. A PL/SQL támogatja az alapvető SQL utasításokat.
Támogatott adattípusok
A következőkben megvizsgáljuk az Oracle alapvető adattípusait, valamint megadjuk azok megfelelőit az MS SQL Server rendszerben. Használni később csak azt a néhány adattípust fogjuk, amelyet mind a PL/SQL nyelv, mind pedig a .NET rendszer támogat.
Az Oracle adattípus-listája, összevetve az SQL Server jól megszokott listájával nem tűnik hosszúnak, azonban látni fogjuk, hogy egy-egy adattípus megfelel jó néhány SQL Serveres típus együttesének, mintegy kiváltva azt. Ez jól tükrözi, hogy az Oracle cég elsősorban nagygépes környezetre fókuszálta rendszerét. Az alábbi típuslista tájékoztató jellegű, ismertetése után felsoroljuk azt a néhány típust, melynek megvan a PL/SQL-oldali támogatása is.
| Oracle adattípus |
Definíció |
| CHAR |
Fix hosszúságú karakteres adattípus, minimális mérete 1, maximális mérete 2000 karakter. |
| DATE |
Dátum adattípus. Lehetséges értékei: ie. 4712-től isz. 4712-ig. |
| DECIMAL |
Megegyezik a NUMBER típussal. |
| FLOAT |
Megegyezik a NUMBER típussal. |
| INTEGER |
Megegyezik a NUMBER típussal. |
| LONG |
Számértékek tárolása legfeljebb 2GB méretben. |
| LONG RAW |
Nyers adatok tárolására. Megegyezik a LONG típussal. |
| LONG VARCHAR |
Megegyezik a LONG típussal. |
| NUMBER(<jegyek>,<tizedesek>) |
Számértékek tárolására szolgál. Tizedesek megadása nélkül a numerikus értékeket egész számmá kerekíti. Max. értéke: 9.99..E125. |
| SMALLINT |
Megegyezik a NUMBER típussal. |
| RAW |
Nyers bináris adatok tárolása legfeljebb 255 bájt méretben. |
| VARCHAR2 |
Legfeljebb 4000 bájtos karakterlánc tárolására. |
| VARCHAR |
Megegyezik a VARCHAR2 típussal. |
| BLOB |
Nagyméretű bináris objektumok tárolása legfeljebb 4GB méretben. |
| COB |
Nagyméretű karakteres objektumok tárolása legfeljebb 4GB méretben. |
| BFILE |
Mutató egy bináris állományra. |
Lássunk néhány megfeleltetést a MS SQL Server adattípusaival.
| SQL Server 2000 adattípusai |
Oracle adattípusai |
| bigint |
NUMBER |
| binary |
LONG RAW NOT NULL |
| bit |
NUMBER(1,0) |
| char |
VARCHAR2(900) NOT NULL |
| datetime |
DATE |
| decimal |
NUMBER(255,3) NOT NULL |
| float |
FLOAT NOT NULL |
| image |
LONG RAW |
| int |
NUMBER(255,3) NOT NULL |
| money |
NUMBER(255,3) NOT NULL |
| nchar |
VARCHAR2(2000) NOT NULL |
| ntext |
LONG |
| numeric |
NUMBER(255,3) NOT NULL |
| nvarchar |
VARCHAR2(2000) NOT NULL |
| real |
FLOAT NOT NULL |
| smallint |
NUMBER(255,3) NOT NULL |
| smalldatetime |
DATE NOT NULL |
| smallmoney |
NUMBER(255,3) NOT NULL |
| sql_variant |
LONG |
| sysname |
CHAR(255) |
| text |
LONG |
| timestamp |
RAW(255) |
| tinyint |
NUMBER(255,3) NOT NULL |
A lista tovább szűkül, ha figyelembe vesszük, hogy a .NET-es rendszerben milyen módon érhetjük el Oracle adatbázisunkat. Az adatbázis a .NET natív OleDB Provider-ét használja, melyet a System.Data.OleDb névtér reprezentál. Ennek megfelelően a támogatott típusok: NUMBER, CHAR, VARCHAR, VARCHAR2, DATE.
Gyakorlati felhasználás
A mellékelt példában az Oracle02.sql script lefuttatása után létrejön egy Table2 adattábla. A tábla első oszlopa rendelkezik egy elsődleges kulccsal. A táblába a Form-ra felhelyezett DataGrid kontrolon keresztül lehet új rekordokat beszúrni, meglévő rekordokat módosítani, valamint törölni.
Az adatbázis eléréséhez felhasználtunk egy OleDbConnection komponenst, melynek ConnectionString property-jét előre megadtuk. A szerver neve természetesen az a név, melyen megtalálható a SOUSER felhasználó.
Provider=MSDAORA.1;Password=souser;User ID=souser;Data Source=soserver
Az adatok lekérdezése szokásos módon, egy DataSet adatszerkezetben történik, melyet egy OleDbDataAdapter komponens Fill metódusa tölt fel. A háromféle adatmanipulációs utasítás elvégzéséhez az OleDbDataAdapter komponensben megadtunk három függvényt, melyek CommandText property-je tartalmazza a három utasítást, úgymint az INSERT, DELETE és UPDATE utasításokat.
Sorok beszúrásakor és módosításakor a DataSet adatszerkezet táblájának RowChanged eseményére megadott eseménykezelő kódja fut le, míg törléskor a tábla RowDeleting eseményére megadott kezelőfüggvény kódja.
ds.Tables[0].RowChanged += new System.Data.DataRowChangeEventHandler(this.ds_RowChanged);
ds.Tables[0].RowDeleting += new System.Data.DataRowChangeEventHandler(this.ds_RowDeleting);
Sorok beszúrásakor és módosításakor a kezelőfüggvényben meg kell vizsgálni, hogy milyen jellegű változás történt. Ehhez a System.Data névtér DataRowAction típust használjuk. Sor beszúrásakor értéke Add, míg módosításkor Change.
Miután meghatároztuk az esemény típusát, összeállítjuk az adott utasítás karakterláncát. Mindkét esetben a kezelőfüggvény DataRowChangeEventArgs paraméterét használjuk annak meghatározására, hogy melyik rekordban történt változás. A paraméter Row property-je tartalmazza az érintett rekordot. Az INSERT utasítás tehát a következő lesz:
private void ds_RowChanged(object sender, System.Data.DataRowChangeEventArgs e)
{
if (e.Action == DataRowAction.Change)
{
DateTime dt = new DateTime();
dt = (DateTime)e.Row[3];
update.CommandText = "UPDATE Table2 SET NAME = '" + e.Row[1] + "', DESCRIPTION = '" + e.Row[2] + "', REG_DATE = TO_DATE('" + dt.ToString("dd-MM-yy") + "','DD-MM-YY') WHERE (ID = ";
update.CommandText += e.Row[0] + ")";
update.ExecuteNonQuery();
}
Az UPDATE utasítás pedig a következő:
else if (e.Action == DataRowAction.Add)
{
DateTime dt = new DateTime();
dt = (DateTime)e.Row[3];
insert.CommandText = "INSERT INTO Table2 VALUES (" + e.Row[0] + ",'" + e.Row[1] + "','" + e.Row[2] + "',";
insert.CommandText += "TO_DATE('" + dt.ToString("dd-MM-yy") + "','DD-MM-YY'))";
insert.ExecuteNonQuery();
}
}
A DATE típusú oszlop adatainak bevitele és módosítása némi magyarázatot igényelhet. Az ilyen típusú adatok megadásakor használnunk kell egy TO_DATE nevű beépített függvényt, melynek első paramétere tartalmazza a rögzítendő dátumot karakteresen, második paramétere pedig azt a karakterlánc-mintát, amilyen formátumban a dátumot megadtuk az első paraméterben. Bármilyen különbség illeszkedési-hibát okoz. Természetesen vannak variációk, mi most a legegyszerűbb módot választottuk, vagyis egy DateTime osztályú objektumba tettük az oszlop értékét, majd ennek ToString metódusával megformáztuk.
Rekordok törlésekor egyszerűbb a helyzet, mivel itt csak a törölt rekord első oszlopának értékét kell megtudnunk. A RowDeleting esemény kezelője a következő:
private void ds_RowDeleting(object sender, System.Data.DataRowChangeEventArgs e)
{
delete.CommandText = "DELETE FROM Table2 WHERE ID = " + e.Row[0].ToString();
delete.ExecuteNonQuery();
}