A megelőző részben tett kis kitérőnk után (aki nem emlékezne, egy konkrét példaprogramot irtunk az addig tanultak felhasználásával, egy telefonszám nyilvántartó programot készítettünk) folytassuk az adatelérési komponensek megismerését.

A Query Komponens

A komponens segítségével SQL (Structured Query Lagguage) utasításokat futtathatunk a Delphiben irt programunkból. Az SQL-ről a korábbi adatbázis-kezelési cikkeinkben olvashattok részletesebben. Az SQL az adatbázis-szerverek leggyakrabban használt lekérdező nyelve (pl. Interbase, Sybase, Oracle), de a BDE lehetővé teszi, hogy SQL utasításokat adjunk ki lokális táblákra is. (pl. dBase, Paradox, Acces stb.) Lokális táblák esetén a BDE az un. Local SQL-t használja, ami ugyan nem tartalmazza az SQL92 szabvány összes lehetőségét, azonban azokat az utasításokat igen, amelyekre ezeknél az adatbázisoknál szükségünk lehet. Adatbázis-szerverek eléréséhez az ún. SQL Links csomagot kell használnunk. Delphiben készíthetünk heterogén lekérdezéseket is, vagyis olyan lekérdezést, amelyben a táblák különböző típusú adatbázisokból származnak. (pl. az egyik tábla egy Interbase a másik Paradox)

A Query komponens is a TdataSet ős leszármazottja, így az ott tárgyalt fontosabb tulajdonságok rá is érvényesek. Amennyiben a query futtatásának hatására egy eredményhalmazt kapunk vissza (SELECT utasítás), akkor ebben az eredményhalmazban rekordra pozícionálhatunk, egy mező értékére kereshetünk, származtatott mezőket hozhatunk létre, mezők jellemzőit állíthatjuk be a mezőszerkesztőben, stb.

Most pedig következzenek azok a fontosabb tulajdonságok és metódusok, melyekről korábban még nem volt szó a TdataSet ismertetésekor. (azaz a Query egyéni tulajdonságai)
 

Property Leírás
Params Paraméterek megadására szolgál, paraméteres lekérdezéseknél használjuk.
RequesLive Lehetőség van olyan lekérdezések készítésére, melynek eredményhalmaza szerkeszthető. (de csak akkor, ha megfelel bizonyos, az SQL92 által definiált szerkesztési feltételeknek)
SQL Tstrings objektum, mely a futtatandó SQL utasítást tartalmazza
ParamCheck Ha true, akkor minden olyan esetben, amikor futási időben megváltozik az SQL property, a paraméterek újra generálódnak.

 
 
Metódus Leírás
ExecSQL Query futtatása. Akkor használjuk, amikor olyan SQL utasítást futtatunk, ami nem ad vissza eredményhalmazt. Ellenkező esetben az Open metódust használjuk.
Prepare Hatására a BDE vagy az adatbázis-server előre lefoglalja a query futtatásához szükséges erőforrásokat, így a query gyorsabb lesz.
UnPrepare A Prepare-re lefoglalt erőforrások felszabadítására szolgál.

A Query komponens használata szerkesztési időben

Egy példán keresztül fogjuk megnézni, hogy hogyan is kell használni a query komponenst.

  • Tegyünk egy Query komponenst a form-ra.
  • Állítsuk be a DatabaseName tulajdonságot. Itt megadhatunk aliast, vagy egy könyvtárat, amely az adatbázisfájlokat tartalmazza lokális adatbázisok esetén, illetve egy Database komponens nevét (később lesz róla szó, adatbázis-szerverekehez való csatlakozásnál fogjuk használni) amennyiben azt korábban elhelyeztük a form-on. Jelen esetben állítsuk be a már jól ismert DBDEMOS aliast.
  • Az SQL property-ben kell megadnunk azt az SQL utasítást, amit futatni szeretnénk. Kattintsunk kétszer az SQL property-re, erre bejön egy ablak, ahova beírhatjuk az utasításunkat. Jelen esetben ez nagyon egyszerű lesz, az animals.dbf tábla adatait jelenítjük meg.
Erre a következő SQL utasítás szolgál: SELECT * FROM animals
  • Amennyiben a Query-nk egy lekérdezést tartalmaz, és annak az eredményhalmazát meg akarjuk jeleníteni a képernyőn, akkor még szükségünk van egy adatforrás és egy adatmegjelenítési komponensre (pl. DBGrid) is. Tehát tegyünk egy DBGrid és egy DataSource komponenst a formra és a megfelelő tulajdonságaikat állítsuk be a már korábban megismert módon.
  • A Query futtatására többféle lehetőségünk is van. Ha már szerkesztési időben szeretnénk látni egy lekérdezés eredményét, akkor az Active property-t állítsuk true-ra. Futási időben, ha a Query-nk eredményhalmazt szolgáltat, akkor használjuk az Open, egyébként pedig az ExecSQL metódust.
Tehát nincs más dolgunk, mint az Active property true-ra állítása, és ha mindent jól csináltunk, máris meg kell hogy jelenjenek a tábla rekordjai a DBGrid-ben.

SQL utasítások futási időben

Az SQL property-t futási időben is szerkeszthetjük, módosíthatjuk.

  • Amennyiben a Query meg van nyitva, zárjuk be a Close metódussal.
  • Ha a property már tartalmaz utasítást, azt a Clear metódussal tudjuk törölni.
  • Új sor hozzáadására az Add metódus szolgál.
  • Ezek után már csak futtatni kell a query-t.
Lássunk erre egy példát:
 
 
with Query1 do 
begin
  Close; {Query bezárása}
  with SQL do 
  begin
    clear; {korábbi utasítás törlése}
    add(‘SELECT * FROM animals'); {sor hozzáadása az SQL 
         utasításhoz}
    add(‘WHERE weight = 34');
  end;
  Open; {query aktiválása}
end;

Szükségünk lehet rá, hogy egy létező SQL utasításnak csak egyetlen sorát módosítsuk. Ezt a következőképpen tudjuk megtenni:

Query1.SQL[1]:='WHERE weight = 34';

Tehát a Tstrings típusú SQL property-re soronként is hivatkozhatunk.

SQL utasítások file-ból

A LoadFromFile metódus segítségével, szöveg formátumú file-ból is betölthető egy SQL utasítás. A metódust automatikusan törli a property megelőző tartalmát, amennyiben volt. Lássuk, hogyan kell:
 
 

Query1.Close;
Query1.SQL.LoadFromFile(‘c:\orders.txt');
Query1.Open;

SQL utasítások string list objektumból

Az Assign metódus segítségével, string lista objektumból tölthetünk be SQL utasításokat az SQL property-be. Így pl. egy Memo komponensbe beírt utasítást tudunk egyszerűen futtatni.

Ezt felhasználva, most írunk egy rövid kis programot, amivel tetszőleges táblákra tetszőleges SQL utasításokat adhatunk ki.

  • Nyissunk egy új projectet.
  • Tegyünk a formra egy Query, egy DataSource, egy Edit, egy Memo, két Label és egy DBGrid komponenst. Az Edit komponensbe fogjuk beírni az alias nevét, a Memo-ba az SQL utasítást majd futási időben, a Query futtatásaként létrejött eredmények pedig a DBGridben fognak megjelenni.
Egy ehhez hasonló felületet hozzunk létre:

  • A DataSource komponens DataSet property-jét állítsuk a Query-re, a DBGrid DataSource property-jét pedig az adatforrásra.
  • A "Futtat" gomb, onClick eseményjellemzőjébe írjuk be a következő kódot:
procedure TForm1.FuttatClick(Sender: TObject);
begin
  Query1.Close; {Query zárása}
  Query1.DatabaseName:=Edit1.text; {Az alias az Edit-ből származik}
  Query1.SQL.Assign(Memo1.Lines); {A memo sorait az SQL property-be töltjük} 
  Query1.Open; {Aktiváljuk a query-t}
end;

Ennyi az egész, már el is készült a kis SQL lekérdezés futtató programunk. Futtassuk a programot, írjuk az Edit-be, hogy DBDEMOS, a memo-ba pedig a köv. utasítást: ‘SELECT * FROM animals'. A "Futtat" gombot megnyomva a Grid-ben megjelennek az animals.dbf rekordjai.

Paraméterek használata SQL utasításokban

Paraméterek segítségével változó értékeket használhatunk az SQL utasításainkban, hasonlóan ahhoz, ahogyan Object Pascalban használjuk a változókat. A könnyebb megértés érdekében kezdjük is rögtön egy példával.
 

SELECT *
    FROM orders
    WHERE saledate = :pDatum

Az SQL kifejezésben ":" (kettőspont) jelzi, hogy utána egy paraméter következik, tehát az ott található változó értékét kell behelyettesíteni a kifejezésbe. A fenti lekérdezés a rendelések táblából azokat a rendeléseket gyűjti ki, amelyek eladási dátuma megegyezik a paraméterben átadott dátummal. A dátumot bekérhetjük egy Edit komponensben, majd az StrToDate() függvénnyel a bevitt stringet dátummá alakíthatjuk.

A paramétereket meg tudjuk adni szerkesztési és futási időben is.

  • Szerkesztési időben ez a params property segítségével lehetséges. Kettőt klikkelve rajta, bejön egy lista, ami az SQL property-be írt SQL utasításunk paramétereit tartalmazza. Itt ki lehet választani a tetszőleges paramétert, és annak be lehet állítani a típusát, értékét.
  • Futási időben is használhatjuk a params tulajdonságot, vagy pedig a ParamByName metódust.
    Lássunk ezekre egy-egy példát:

    Paraméter a params property segítségével:
    Query1.Params[0].AsDate:=StrToDate(Edit1.Text);

    Paraméter a ParamByName metódus segítségével:
    Query1.ParamByName(‘SaleDate').AsDate:=StrToDate(Edit1.Text);
     

Paraméterek másik adathalmazból

A Query komponens a DataSource property-je lehetővé teszi, hogy a paramétereit egy másik adathalmaz aktuális rekordjából nyerje. Ezáltal SQL lekérdezéssel is kialakíthatunk master-detail kapcsolatot.

Nézzük meg egy példán keresztül, hogy hogyan is kell ezt megvalósítani. Elkészítjük a korábbi master-detail-os példánk SQL-es változatát.

  • Kezdjünk egy új projectet.
  • Helyezzünk a formra egy Table, egy Query, két DataSource, két DBGrid és egy DBNavigator komponenst.
  • A Table és a Query DatabaseName tulajdonsága legyen a már megszokott DBDEMOS. A TableName pedig legyen a customers.db. Az egyik adatforrás komponenset állítsuk a Table-re, a másikat a Query-re. Az egyik DBGridben a Tábla adatait, a másikban pedig majd a Query adatait fogjuk megjeleníteni (ennek megfelelően állítsuk be a DataSource tulajdonságokat). A DBNavigartor-t a táblára állítsuk.
  • A Query DataSource tulajdonságát állítsuk a táblához tartozó adatforrás komponensre.
  • Ezután meg kell adnunk az SQL utasításunkat az SQL propertyben. Ez a következő lesz:
SELECT * FROM orders WHERE custno = :custno
    Ennek hatására csak azokat a rendeléseket gyűjti ki, amelyekben az ügyfél azonosító megegyezik a paraméterben átadottal. A paraméter pedig a korábbi beállítások révén, a customers.db tábla aktuális rekordjának CustNo mezőjében lévő értéket tartalmazza.
  • Most már csak meg kell nyitnunk az adathalmazokat. A megnyitó metódusokat a form onCreate eseményjellemzőjébe tegyük. A prepare metódus segítségével előre lefoglaljuk a query számára szükséges erőforrásokat.
    Ezt írjuk a form onCreate eseményjellemzőjébe:
Table1.Open;
Query1.Prepare;
Query1.Open;
  • Futtatva a programot és a tábla rekordjain lépkedve látható, hogy a query-re állított DBGrid mindig csak a kiválasztott ügyfél rendeléseit jeleníti meg.

Master-Deatil SQL-el. Csak a kiválasztott ügyfél rendelései jelennek meg.

Alias az SQL kifejezésben

A DBE lehetőséget biztosít arra is, hogy az adatbázis alias-át ne a DatabaseName tulajdonságon keresztül adjuk meg, hanem az SQL kifejezésben. Ezáltal heterogén lekérdezéseket hozzunk létre, vagyis olyan lekérdezéseket, amelyekben a felhasznált táblák különböző adatbázisokból származnak.

Ha az aliast az SQL kifejezésben akarjuk megadni, akkor a következő szintaxis szerint kell eljárnunk:

":alias_neve:tábla_neve"

Példa:

SELECT *
    FROM ":DBDEMOS:customer.db"

Példa heterogén lekérdezésre:

    SELECT *     FROM ":DBDEMOS:customer.db" C, ":DB2_DEMOS:orders.db" O     WHERE (C.custno = O.custno)
A két alias ebben a példában ugyanarra az adatbázisra mutat, de azt is megtehetjük, hogy az egyik adatbázis pl. Paradox, míg a másik Interbase stb.

A DataSource Komponens

A DataSource komponensről korábban már érintőlegesen volt szó. Feladata, hogy összekapcsolja az adatelérési és adatmegjelenítési komponenseket.

Feltehetnénk a kérdést, hogy miért nem kapcsolódnak az adatelérési komponensek közvetlenül az adatmegjelenítési komponensekhez? Nos, az adatforrás komponensnek több előnye is van:

  • Van egy adatelérési komponensünk, aminek adatait a programunkban jó néhány helyen megjelenítünk különböző adatmegjelenítési komponensek segítségével. Ha a későbbiek során ezt le akarjuk cserélni (pl. Table-ról, Query-re), akkor csak a DataSource komponens DataSet property-ét kell az új adatelérési komponensre állítani, és nem kell minden egyes adatmegjelenítési komponenssel külön foglalkoznunk.
  • Ha több, azonos szerkezetű adathalmazt akarunk megjeleníteni, akkor ezekhez elég egy űrlapot terveznünk, és csak az űrlapon lévő adatmegjelenítési komponensek adatforrásának DataSet tulajdonságát kell a különböző adathalmazokra állítgatnunk. (ezt ugyebár programból, futási időben is megtehetjük)
A DataSource komponens kevés tulajdonsággal és eseménnyel rendelkezik. Nézzük ezeket:
 
Property Leírás
AutoEdit True értékekor, ha a felhasználó egy adatmegjelenítési komponensben valamilyen módon szerkesztést kezdeményez, akkor arra lehetősége is lesz. Ha False, akkor csak az Edit metódus meghívása után lehetséges a szerkesztés.
DataSet Az adatmegjelenítési komponens neve, amelynek adatait szolgáltatja az adatmegjelenítési komponenseknek.
Enabled Ha True, akkor az adathalmaz által szolgáltatott adatok megjelennek az adatforráshoz csatlakozó adatmegjelenítési komponensekben, egyébként nem.
State Az adathalmaz állapota, amelynek az adatait a komponens szolgáltatja

 
 
Metódus Leírás
OnDataChange Egy rekord editálásakor, illetve egy másik rekordra mozgáskor hívódik meg.
OnStateChange Egy adathalmaz állapotának megváltozásakor hívódik meg.
OnUpdateData Akkor hívódik meg, ha egy rekord egy mezőjének értékét megváltoztatjuk, vagy új rekordot veszünk fel a táblába.

A DataSource komponens működését szemléltető ábra található a cikksorozat első részében.