Delphi - Interbase 6 alkalmazása Delphi-ben

Interbase 2. rész

forráskód letöltése
Az előző rész elméleti fejtegetése után mostantól csak gyakorlati kérdésekkel foglalkozunk. Jelen írásban az InterBase Express csomag TIBInstall komponensének tulajdonságait és metódusait ismerhetjük meg. Példaprogramot írunk a komponens lehetőségeinek gyakorlati bemutatására. A TIBInstall (és az őse, a TIBSetup) lehetőséget biztosít arra, hogy az InterBase 6.0 adatbázis-kezelőt saját programunk által telepítsük. Ezáltal olyan telepítőt írhatunk, amelyik saját igényeinknek megfelelő. Beállítjuk a telepítés forrás- és célkönyvtárát, a telepíteni kívánt összetevőket és már indulhat is a procedúra. Ezekről a lehetőségekről lesz szó a következő részben.

Nézzük meg, hogyan készíthetünk egy olyan telepítő alkalmazást, amelyik lehetőséget biztosít a felhasználó számára a kívánt komponensek kiválasztásáról, és hogyan tájékoztathatjuk a folyamat pillanatnyi állásáról.

A következő tulajdonságokat állíthatjuk be a komponens használata előtt:
  • Az InstallOptions tulajdonság lehetőséget biztosít arra, hogy kiválasszuk mely InterBase komponensek legyenek telepítve az adott gépen. A lehetőségeket a TInstallOptions osztály írja le. Ha egy lehetőséget igazra állítunk, az telepítve lesz a felhasználó gépén. A tulajdonság részletes ismertetése a későbbiekben történik.
  • DestinationDirectory a telepítés célkönyvtárát állítja be vagy adja vissza. Ha az értékét nem állítjuk be és az alkalmazást egyszer már telepítettük, akkor az alapértelmezett értékeket szolgáltatja, amelyek a Windows Registry-ben találhatók meg.
  • MsgFilePath azt a könyvtárat állítja be vagy adja vissza értékként, amelyikben az ibinstall.msg fájl megtalálható (lesz).
  • Progress tulajdonság egy 0 és 100 közé eső egész számot ad vissza, amelyik arról tájékoztat, hogy a telepítés hány százalékán van már túl a program. Értékét egy folyamatsávon keresztül jelezhetjük a felhasználó felé.
  • RebootToComplete tulajdonság igaz értéke jelzi, ha a telepítés végén a gépet újra kell indítani. Alapértelmezett értéke: hamis. Megjegyzendő, hogy a dokumentáció szerint ez a tulajdonság írható és olvasható, ha azonban a forráskódban meg szeretnénk változtatni értékét, fordítási hibával leállna a fordító.
  • SourceDirectory tulajdonsággal beállíthatjuk vagy megkaphatjuk annak a könyvtárnak a nevét, ahonnan a programot telepítjük.
  • UnInstallFile visszatér az uninstall fájl nevével és elérési útvonalával, amelyik a program eltávolításához szükséges és a telepítés beállításait tartalmazza.
Most vizsgáljuk meg részletesen az InstallOptions tulajdonság beállítási lehetőségeit:
CmdLineTools segítségével a parancssoros eszközöket telepíthetjük. Három lehetőséget tartalmaz:
  • cmDBMgmt: a gbak és a gfix programok telepítési lehetősége. Ha nincs bejelölve az InterBase Client pont (moClient tulajdonság) figyelmeztető üzenetet kapunk a telepítéskor.
  • cmDBQuery: isql, gdwf, qli adatbázis-lekérdező programokat jelenti. Szintén szükséges hozzá az InterBase Client pont (moClient tulajdonság) bejelölése.
  • cmUsrMgmt: a gsec felhasználókezelő segédprogram telepítése. InterBase Client (moClient tulajdonság) pont bejelölése szükséges.
ConnectivityClients: Az összekapcsolódási lehetőségeket telepíthetjük. Három lehetőséget választhatunk:
  • cnODBC: az Open Database Connectivity kliens.
  • cnOLEDB: OLE DB kapcsolati lehetőség.
  • cnJDBC: InterClient Java kapcsolati lehetőség.
Examples: Példák telepíthetők a tulajdonság segítségével. Az alábbi két lehetőség van:
  • exAPI: API, SQL, DSQL és az ESQL példák telepíthetők a célszámítógépekre. Az InterBase Clientet (moClient tulajdonság) és a fejlesztői segédletet (moDevelopment tulajdonság) telepíteni kell.
  • exDev: adatbázispéldák. Az InterBase Server-t (moServer tulajdonság) telepíteni kell.
Maincomponents: Az InterBase rendszerünk legfontosabb részeit telepíthetjük. Az alábbi hat tulajdonságot állíthatjuk be:
  • moServer: A szerver program. A következők lesznek telepítve, ha ezt a pontot bejelöljük: a szerver, a licensz és az üzenet fájl, a Guardian, szerver beállítási segédprogram, adatbázis információs segédek, UDF és a nemzetközi karakterkészletet beállító eljáráskönyvtárak, valamint a súgó állományok.
  • moClient: A kliens program. Telepítésre kerül a kliens eljáráskönyvtár, a licensz és az üzenet fájlok.
  • moConServer: a beállításának nincs semmi gyakorlati jelentősége, csak későbbi fejlesztésekre van fenntartva.
  • moGuiTools: Grafical Interface Tools, az IBConsol alkalmazás.
  • moDocumentation: A dokumentációk a program használatáról és fejlesztői segédletek.
  • moDevelopment: fejlesztői segédletek gpre parancssori program, import eljáráskönyvtárak és a header fájlok.
A következő hasznos tulajdonságokkal rendelkezik még a komponens:
  • SuggestedDestination: az ajánlott telepítési célkönyvtárral tér vissza.
  • ErrorContext: visszaadja vagy beállíthatjuk a hibaüzenetet.
  • StatusContext: visszaadja vagy beállíthatjuk a telepítés folyamán megjelenő tájékoztató üzeneteket.
Az TIBInstall komponens metódusai:
  • InstallCheck: ellenőrizhetjük azt, hogy minden készen áll-e a telepítés megkezdéséhez.
  • InstallExecute: a telepítés folyamatát végrehajtó metódus.
  • GetOptionSpaceRequired: visszatér a megadott opció (TCmdOption, TConnectivityOption, TExamplesOption, TMainOption) által szükséges lemezterülettel, kilobájtban.
  • GetOptionName: a megadott opció (TCmdOption, TConnectivityOption, TExamplesOption, TMainOption) nevével tér vissza.
  • GetOptionDescription: a függvény visszatér a megadott opció (TCmdOption, TConnectivityOption, TExamplesOption, TMainOption) leírásával.
A TIBInstall komponens eseményei:
OnError:
function TForm1.IBInstall1Error(Sender: TObject; IscCode: Integer; ErrorMessage, ErrorComment:
    String): TErrorResult;
Ez az esemény akkor következik be, amikor hiba történik a telepítés folyamán. A visszatérési értékkel határozhatjuk meg, hogy mi történjen:
  • srContinue: a telepítés folytatódjon,
  • srRetry: próbálja újra a hibás részt telepíteni,
  • srAbort: a telepítés fejeződjön be.
OnStatusChange:
function TForm1.IBInstall1StatusChange(Sender: TObject; StatusComment: String): TStatusResult;
Az esemény bekövetkezik, amikor a telepítés állapotában változás történik. Ez az esemény időről-időre bekövetkezik miután meghívtuk az InstallExecute metódust. Itt tájékoztathatjuk a felhasználót a telepítés folyamatáról. A StatusComment paramétert használhatjuk szöveges tájékoztatásra. Ebben az eseményben frissíthetjük programunk állapotsávját a komponens Progress tulajdonságát felhasználva.

OnWarning:
function TForm1.IBInstall1Warning(Sender: TObject; WarningCode: Integer;  WarningMessage: String):
    TWarningResult;
Az esemény akkor következik be, amikor a telepítés folyamán valamilyen figyelmeztetés keletkezik valamilyen ok miatt. A függvény visszatérési értéke vagy srContinue vagy srAbort lehet. A figyelmeztetést kiváltó okra a WarningCode és a WarningMessage paraméterekből következtethetünk.

Ennyi elméleti bemutatás után most már megnézhetjük, hogyan tudjuk a komponens segítségével telepíteni az InterBase 6.0 relációs adatbázis-kezelő rendszert. Érdemes a forráskódot is részletesen megnézni a mellékletben, mert azokban találhatunk majd magyarázatokat. Itt csak egy felsorolásban megemlítjük, hogy milyen komponenseket használunk a példában:
  • IBInstall komponens. Az InstallOptions tulajdonság egyes értékei igazra vannak állítva.
  • Egy NoteBook komponens hat lappal.
  • Egy Panel komponens, amire egy Image komponenst helyeztünk.
  • Egy Bevel komponens a gombok elválasztásához.
  • Három darab, különböző funkciójú gomb.
  • Négy Memo komponens hosszabb szövegek megjelenítéséhez.
  • Nyolc Label komponens rövidebb információkhoz.
  • Egy CheckListBox a telepítendő komponensek meghatározásához.
  • Egy Edit komponens a telepítés célkönyvtárának megadása miatt.
  • Egy SpeedButton komponens, amelyik a könyvtárválasztó párbeszédablakot jeleníti meg.
  • Egy másodlagos Form a következő vezérlőkkel:
- Egy Label komponens, amely a telepítésről közöl szöveges információkat.
- Egy Gauge komponens, amelyik a telepítés pillanatnyi állapotát mutatja.
- Egy gomb, amellyel a telepítés megszakítható.

A példaprogram a PÉLDA nevű könyvtárban található.
Ahhoz, hogy a komponenst használni tudjuk, olyan helyre kell rakni a ibinstall.dll-t, hogy programunk elérhesse (például …\Delphi5\bin, vagy abba a könyvtárba, ahonnan a telepítő fut).
A unit1.pas állomány 77. sorát módosítani kell.


Néhány gondolatot ismerjünk meg az adatmodellezés és az adatbázis-tervezés kérdéseiről. Természetesen a téma nagysága miatt csak a legalapvetőbb problémákat nézzük át.
Az adatbázis-kezelő alkalmazások esetében három fő funkcionális egységet különböztetünk meg:

1. Közvetlen adatkezelés
A tárolt adatok fizikai feldolgozása, állományok nyitása, zárása, indexelése, lekérdezés optimalizálása és futtatása, adatok felvitele, módosítása, törlése és a zárolási konfliktushelyzetek megoldása tartozik ide. Ez a rész függ a használt adatbázis-formátumtól.

2. Alkalmazás-logika (Business logic)
A teljes alkalmazás helyes működése: adatok védelme (felhasználói jogosultságok), elronthatatlansága (integritás), hatékony és kényelmes csoportosítás, tranzakció-kezelés.

3. Felhasználói felület (User Interface)
A felhasználóval való közvetlen kapcsolattartás. Tetszetős, barátságos, de elronthatatlan (a felhasználói felület elemeinek helyes működése). Az adatok helyességéért viszont az alkalmazás-logika felelős.

Ehhez a három részhez tartozik még egy utolsó, a fizikai adatbázis, de ezt nem szoktuk az alkalmazás részének tekinteni.
Az adatmodell elkészítése az adatbázisos feladatok fejlesztésének leglényegesebb pontja. Az adatmodellnek kellően komplexnek kell lennie ahhoz, hogy minden programfunkciót kielégítsen. Másrészről viszont vigyázni kell, hogy fölösleges adatokkal ne bonyolítsuk rendszerünket. Csak a konkrét feladat szempontjából fontos adatokat kell tárolnunk.

Az alkalmazás-logika

Alkalmazáslogikának nevezzük az adatbázisra vonatkozó szabályok összességét, más szóval az adatbázis működési szabályait. Ilyenek:
  • Mezőszintű ellenőrzés. Például 1000 < irányítószám <9999 (hazánkban).
  • Rekordszintű ellenőrzés. Például egy vásárlás dátuma < eladás dátuma.
  • Hivatkozási integritás. Egy gépkocsihoz csak akkor lehet tulajdonost hozzárendelni, ha adatait már nyilvántartjuk.
  • Komplex ellenőrzések. Például egy személynek csak egy jogosítványa lehet.
  • Egyéb adatbázis-működést befolyásoló eljárások. Például: gépkocsi eladása a gépkocsi korábbi tulajdonosainak a száma.
Adatbázis-logika megvalósítása
Vizsgáljuk a kliens/szerver felépítés kínálta lehetőséget. Adott egy adatbázis és van egy kliens oldali alkalmazás. Az alkalmazás-logikát több szinten is beépíthetjük: adatbázis-megszorítások (constraints), kapcsolatok, triggerek, tárolt eljárások. Ha mindezek az adatbázisban vannak, akkor nem kerülhetők ki függetlenül attól, hogy Delphi alkalmazásból vagy más programból kezeljük az adatokat. Ezért jó az alkalmazás-logika az adatbázisban. A gyakorlatban van olyan szabály, amelyeket nem lehet célszerűen, vagy csak bonyolult módon lehet az adatbázisba építeni. Például ilyen a telefonszámok esete. Ha ezt a kliens oldali alkalmazásba helyezzük, akkor a beállítást minden bemeneti mezőben külön-külön meg kell adnunk. Ha változik a telefonszám formátuma, mindenhol újra be kell azt állítani. Ez nem túl hatékony módszer, ezért használhatjuk az adatszótárakat. Erről részletesen a súgóban tájékozódhatunk.
Azonban ha többrétegű alkalmazást írunk, akkor használnunk kell a TClientDataSet komponenst, amely igen hatékony lehetőségeket biztosít számunkra többek között a fenti probléma megoldására is. Erről a sorozat utolsó részében egy rövid ismertetőt olvashatunk majd.

Lássuk, hogy milyen mezőket használhatunk egy InterBase adatbázis kezelésekor:
  • Char(n): Egy n karakterből álló karakterláncot jelöl. Legnagyobb mérete a kiszolgálótól és az illesztőprogramtól függ. (InterBase esetében 32767 karakter)
  • Int, integer: Egész szám, általában négy bájt, de ez platformfüggő.
  • Smallint: Kisebb egész szám, általában két bájt.
  • Float: Lebegőpontos szám.
  • Double precision: Kétszeres pontosságú lebegőpontos szám.
  • Numeric (pontosság, helyiérték): Lebegőpontos szám megadott pontossággal és helyiértékkel.
  • Date: Dátum, megvalósítása a kiszolgálótól függ.
  • Blob: Nagy mennyiségű bináris adatot tároló objektum.
  • Varchar: Változó hosszúságú karakterlánc, a rögzített hosszúságú karakterláncok által okozott kellemetlenségek elkerülésére.
A TStringField osztály különbséget tud tenni a char és a varchar típusok között, de egy tulajdonságban tárolja azokat. Így elejét vehetjük annak a problémának, ah a kiszolgáló a char típust szóköz karakterekkel tölti fel. Ez például hibákat okozhat egy WHERE záradékban.
Láthatjuk, hogy nincs például számláló vagy logikai típusú mező. Az előzőt generátorok használatával szimulálhatjuk. Az utóbbi helyett használhatunk smallint típust vagy értéktartományokat. Alkalmazhatjuk a char(1) típust is, az 'F' érték a hamisnak, a 'T' pedig az igaznak felel meg. Tehát, ha egy ilyen mezőben 'T' áll, akkor azt az AsBoolean metódus igaz értékként adja vissza.

Értéktartományok

Az értéktartományokkal (domain) saját adattípusokat hozhatunk létre. Egy meglévő adattípuson alapul, annak egy részhalmaza, szűkítése. Hasznos az adatbázis meghatározásánál, elkerülhetjük vele a külön-külön ellenőrző feltételeket az egyes mezőknél és a leírás olvashatóbb lesz. Hozzuk létre azt a mezőt, amelyben az irányítószámokat fogjuk tárolni:
CREATE DOMAIN IRSZAMMEZO AS INTEGER DEFAULT 1000
CHECK (VALUE BETWEEN 1000 AND 9999)
A fenti utasítás létrehozza a mezőt, alapértelmezett értéket rendel hozzá, és ellenőrzi, hogy az értéke a megadott határok közé esik-e.

A triggerek és a generátorok

A triggerek többé-kevésbé a Delphi eseményekhez hasonlítanak és automatikusan végrehajtódnak, ha az adott esemény bekövetkezik. A triggereknek lehet saját kódja, de meghívhatnak tárolt eljárásokat is. Végrehajtásuk a kiszolgálón történik. A triggereket az adatok épségének és egységességének megőrzéséhez használjuk, segítségükkel az új adatokat összetettebb módon ellenőrizhetjük, mint amennyire a megszorítások ezt lehetővé tennék. Bizonyos beviteli műveletek következményeit is automatizálhatjuk, például naplózhatjuk, hogy az adatokat ki és mikor módosította utoljára.
A triggerek három alapműveletre indulnak el: INSERT, UPDATE és DELETE. Létrehozásuk során megadhatjuk, hogy a művelet előtt vagy után induljanak el.

Az InterBase rendszerben nem létezik számláló típus, azonban van lehetőségünk ennek szimulálására: be kell vezetnünk egy generátort. Ez olyan, mint egy változó, amelynek kezdőértéket is adhatunk.
CREATE GENERATOR TUL_AZON_GEN;
Ezután írnunk kell egy trigget, amely lefut, minden újabb tulajdonos felvételekor, és eggyel növeli a generátor értékét, majd az új tulajdonos azonosítóját erre az értékre állítja be.
CREATE TRIGGER SET_TUL_AZON FOR TULAJDONOSOK
BEFORE INSERT POSITION 0 AS
BEGIN
  NEW.TUL_AZON = GEN_ID(TUL_AZON_GEN, 1);
END
A triggert a TULAJDONOSOK táblához adtuk meg és minden új rekord felvitelénél lefut. A GEN_ID függvény állítja elő az új egyedi azonosítót; át kell adni paraméterként a régi azonosítót, második paraméterként pedig a növelés mértékét. A NEW jelöli azt a rekordot, amit fel szeretnénk venni. A POSITION adja meg a sorszámot abban az esetben, ha több trigger is kapcsolódik ugyanahhoz az eseményhez. A legalacsonyabb értékű trigger fut le először.
A triggerek belsejében használhatunk olyan DML utasításokat, amelyek más táblákat módosítanak, de vigyázni kell a végtelen ciklusra. A triggereket módosítani az ALTER TRIGGER, törölni a DROP TRIGGER utasítással lehet.


Példaprogramunkban tartsuk nyilván a gépkocsik és a tulajdonosaik adatait. Hozzunk létre néhány táblát. Az elsőben tartsuk nyilván a gépkocsi-tulajdonosok, a másodikban a jogosítványok, a harmadikban az autók legfontosabb adatait. A negyedik táblában a gépkocsikkal történő eseményeket rögzítsük.

A tulajdonosok tábla oszlopai:
  • Azonosító: számláló típusú mező,
  • Vezetéknév: szöveges mező,
  • Keresztnév: szöveges mező,
  • Leánykori vezetéknév: szöveges mező,
  • Leánykori keresztnév: szöveges mező,
  • Születési hely: szöveges mező,
  • Születési idő: dátum típusú mező,
  • Anyja leánykori neve: szöveges mező,
  • Személyigazolvány száma: szöveges mező,
  • Állandó lakcím:
- Irányítószám: egész szám,
- Város: szöveges mező,
- Utca: szöveges mező,
  • Telefon: szöveges mező,
  • Feljegyzések: hosszabb szöveges mező (memo),
  • Van-e kocsija: logikai mező,
  • Az adatok rögzítésének időpontja: dátum típusú mező,
  • Az adatokat rögzítő felhasználó: szöveges mező,
  • Az adatok módosításának időpontja: dátum típusú mező,
  • Az adatokat módosító felhasználó: szöveges mező,
A jogosítvány tábla oszlopai:
  • Azonosító: számláló típusú mező,
  • Száma: szöveges mező,
  • Tulajdonosa: a tulajdonosok tábla egy "rekordjára" mutató mező,
  • Kategóriák: szöveges mező,
  • Érvényesség kezdete: dátum típusú mező,
  • Érvényesség vége: dátum típusú mező,
  • Feljegyzések: hosszabb szöveges mező (memo),
  • Az adatok rögzítésének időpontja: dátum típusú mező,
  • Az adatokat rögzítő felhasználó: szöveges mező,
  • Az adatok módosításának időpontja: dátum típusú mező,
  • Az adatokat módosító felhasználó: szöveges mező.
A gépjármű tábla oszlopai:
  • Azonosító: számláló típusú mező,
  • Gyártmány: szöveges mező,
  • Típus: szöveges mező,
  • Alvázszám: szöveges mező,
  • Rendszám: szöveges mező,
  • Motorszám: szöveges mező,
  • Forgalomba helyezés: dátum típusú mező,
  • Színe: szöveges mező,
  • Ajtók száma: szöveges mező,
  • Tulajdonosok száma: egész szám,
  • Hengerűrtartalom: egész szám,
  • Saját tömeg: egész szám,
  • Szállítható személyek száma: egész szám,
  • Teljesítmény: egész szám,
  • Össztömeg: egész szám:
  • Feljegyzés: hosszabb szöveges mező (memo),
  • Az adatok rögzítésének időpontja: dátum típusú mező,
  • Az adatokat rögzítő felhasználó: szöveges mező,
  • Az adatok módosításának időpontja: dátum típusú mező,
  • Az adatokat módosító felhasználó: szöveges mező,
Az események tábla oszlopai:
  • Azonosító: számláló típusú mező,
  • Tulajdonosa: a gépjármű tábla egy "rekordjára" mutató mező,
  • Dátum: dátum típusú mező,
  • Kulcsszó: szöveges mező,
  • Feljegyzés: hosszabb szöveges mező (memo).
  • Az adatok rögzítésének időpontja: dátum típusú mező,
  • Az adatokat rögzítő felhasználó: szöveges mező,
  • Az adatok módosításának időpontja: dátum típusú mező,
  • Az adatokat módosító felhasználó: szöveges mező,
A gépjárműtulajdonosa tábla oszlopa:
  • Azonosító: számláló típusú mező,
  • Tulajdonos: a tulajdonos tábla egy "rekordjára" mutató mező,
  • Gépjármű: a gépjármű tábla egy "rekordjára" mutató mező,
  • Vétel dátuma: dátum típusú mező,
  • Eladás dátuma: dátum típusú mező,
  • Feljegyzés: hosszabb szöveges mező (memo).
  • Az adatok rögzítésének időpontja: dátum típusú mező,
  • Az adatokat rögzítő felhasználó: szöveges mező,
  • Az adatok módosításának időpontja: dátum típusú mező,
  • Az adatokat módosító felhasználó: szöveges mező,
A táblák létrehozását követően definiálhatunk másodlagos indexeket, táblák közötti kapcsolatokat és a számláló típusú mezőket kezelő generátorokat. A táblázatokat tesztadatokkal kell feltölteni. A későbbiek folyamán írunk tárolt eljárásokat, triggereket, és megvizsgáljuk, hogyan lehet egyszerűbben és hatékonyabban kezelni adatbázisunkat ezek segítségével.


Az adatbázis létrehozásához indítsuk el az IBConsole alkalmazást. Válasszuk a Server menü Register… pontját. A megjelenő párbeszédablakban jelöljük be a Locale Server pontot és töltsük ki a User name (SYSDBA) és a Password (masterkey) mezőket, majd kattintsunk az OK gombra. Következő lépésként válasszuk a Database menü Create Database… pontját. Adjunk az adatbázisunknak egy álnevet, majd a táblázat első sorába írjuk be az adatbázis elérési útját. A többi mezőn nem kell változtatnunk. Az OK gomb megnyomása után adatbázisunk létrejön. A táblák létrehozásához a Tools menü Interactive SQL pontját választjuk, majd betöltjük a mellékelt SQL-szkriptet, és lefuttatjuk azt. Végezetül bezárjuk az IBConsole programot.
Természetesen mindezt kóddal is elvégezhetjük úgy, hogy a szkript sorait egyesével futtatjuk egy IBQuery komponens segítségével.


Néhány érdekesebb SQL-kifejezés

Egy szöveges "értéktartomány", amelynek alapértéke a bejelentkezett felhasználó neve:
CREATE DOMAIN "USERNAME" AS VARCHAR(20) DEFAULT USER;
Integer típusú mező, mely nem maradhat kitöltetlenül:
  "ESM_AZONOSITO"	INTEGER NOT NULL,
Egy MEMO típusú mező, amelynek szegmensmérete is meghatározott:
  "FELJEGYZES"	BLOB SUB_TYPE TEXT SEGMENT SIZE 80,
Az ESM_AZONOSITÓ mező az elsődleges index:
PRIMARY KEY ("ESM_AZONOSITO")
Egy dátum típusú értéktartomány, amelynek alapértéke a rendszerdátum:
CREATE DOMAIN "DATUM" AS DATE DEFAULT 'NOW';
A TULAJDONOS mezőben az értékek egyszer fordulhatnak elő:
UNIQUE ("TULAJDONOS"),
A GKTUL tábla TULAJDONOS mezőjéhez hozzárendeljük a TULAJDONOSOK tábla TUL_AZONOSITO mezőjét:
ALTER TABLE "GKTUL" ADD FOREIGN KEY ("TULAJDONOS") REFERENCES TULAJDONOSOK ("TUL_AZONOSITO");

Jegyezzük meg a pontosság kedvéért, hogy az internetről letöltött program nem tartalmazza a dokumentációt, a kapcsolódási lehetőségeket és a licenszkezelést megvalósító programot. Így amikor ezen változat alapján írunk telepítő programot, vigyáznunk kell arra, hogy milyen lehetőségeket adunk meg. Ezért azt tanácsolnánk, ha csak nincs semmilyen nyomós okunk telepítőprogramot írni, használjuk az eredetit.

Interbase cikksorozat