Delphi - MS SQL adatbázis kezelés Delphi-ből

9. rész

forráskód letöltése
Az SQL utasítások megadásának eszköze a Delphi-ben a TQuery komponens. Segítségével egyszerűen kiadhatjuk az előző fejezetben megismert SELECT, INSERT és UPDATE utasításokat. A TQuery használata nagymértékben hasonlít a TTable objektum használatához, hiszen mindketten a TDataSet leszármazottai. A két komponens és társai kapcsolatát a következő ábra mutatja:
TDataSet
    TCustomADODataSet
      TADOCommand
      TADODataSet
      TADOQuery
      TADOStoredProc
    TClientDataSet
    TBDEDataSet
      TNestedTable
      TDBDataSet
        TTable
        TQuery
        TStoredProc
A TQuery komponenst az esetek 99%-ában a SELECT SQL utasítás megvalósítására használjuk. Ebben a vonatkozásában egy query nagyon hasonlóan viselkedik a szűrővel együtt alkalmazott táblához. Két alapvető előnye van a query-nek a táblához képest:
  • Egyszerre több táblát is használhatunk a lekérdezés megszerkesztéséhez, míg a TTable komponens mindig csak egy táblához kötődik.
  • Meghatározhatjuk, hogy mely oszlopokat kérjük el az adatbázistól és a sorokat is hatékonyabban kiválogathatjuk, így hatékonyabban használhatjuk ki számítógépünk és a hálózat erőforrásait.


A query lehet úgymond szó szerinti vagy paraméterezett. A paraméterek használata nagymértékben megkönnyíti a futásidőben változó, felhasználói adatbeviteltől függő adathalmazok lekérdezését. Két legfontosabb property-je az SQL és a Params property. Az előbbivel adhatjuk meg a végrehajtandó SQL utasítást, utóbbi segítségével pedig futásidőben értéket kapó paramétereket köthetünk az utasításhoz.

Az SQL property TStringList típusú, amit könnyedén feltölthetünk akár az Object Inspectorból, akár futásidőben. Ha például a 4. fejezetben létrehozott Test1 aliason keresztül az SQL Server pubs példaadatbázisához vagyunk csatlakozva, és a jobs táblából szeretnénk azokat a munkaköröket leválogatni, amelyek nevében szerepel a manager szó, az SQL property-t egyszerűen beállíthatjuk:
Query1.SQL.Clear;
Query1.SQL.Add('select * from jobs where job_desc
      like ''%manager%''');
Célszerű mindig törölni az SQL property-t feltöltés előtt, nehogy maradjon benne korábbi szöveg. A beírt utasítást a tartalmától függően kétféleképpen hajthatjuk végre.
Ha az utasítás SELECT, vagyis eredményhalmazt generál, Open metódussal hajtjuk végre. Ha eredményhalmaz nincs, vagyis az utasítás INSERT, UPDATE vagy DELETE, akkor az ExecSQL metódust használjuk. Az előbbi példánál maradva:
Query1.SQL.Clear;
Query1.SQL.Add('select * from jobs where
      job_desc like ''%manager%''');
Query1.Open;
Vagy ha csak a munkakörök nevére vagyunk kíváncsiak, és a többi oszlopra nem, akkor:
Query1.SQL.Clear;
Query1.SQL.Add('select job_desc from jobs 
    where job_desc like ''%manager%''');
Query1.Open;
Ahogy korábban már megszokhattuk, az Open metódus hívása kiváltható az Active property True-ra állításával. Nézzünk egy példát az ExecSQL metódus használatára is, és töröljük ki az összes A betűvel kezdődő munkakört.
Query1.SQL.Clear;
Query1.SQL.Add('delete jobs where 
    job_desc like ''A%''');
Query1.ExecSQL;
A dupla aposztrófok helyett használhatjuk a kettős aposztrófot is, mindkettő helyes.
Ha az Open vagy ExecSQL metódust rossz helyen használjuk, exception-t kapunk, ezért ha tervezési időben nem tudjuk, hogy az utasítás ad-e vissza eredményhalmazt, célszerű try..except blokkba zárni és ha keletkezik kivétel, azt lekezelni. Ha Open metódussal nyitjuk meg a query-t és nincs eredményhalmaz, az ENoResultSet kivételt kapjuk.

Az SQL property TStringList típusa további lehetőségeket biztosít számunkra az utasítás beviteléhez. Beolvashatjuk például fájlból.
Query1.SQL.LoadFromFile('c:\sql_1.txt');
Query1.Open;
Ez nagyon hasznos lehet, főleg, ha egy előre letárolt, bonyolult SQL utasítás sorozatot szeretnénk egyszerre végrehajtani. Mivel az SQL property stringek végtelen sorozata, SQL utasításunk bármekkora lehet.

Aztán beolvashatjuk olyan vizuális elemekből is, amelyek szintén TStrings-ben tárolják az információt. Ilyen pl. a TMemo.
Query1.SQL.Assign(Memo1.Lines);
Query1.Open;
Egy SQL utasítás előírás szerinti végrehajtásának lépései a következők:

1. Ha a query még aktív, lezárjuk. (Close)
2. Kitöltjük az SQL property-t, vagyis megadjuk a végrehajtandó SQL utasításunkat.
3. Ha paraméterezett lekérdezést hajtunk végre, kitöltjük a Params property-t is.
4. Meghívjuk a Prepare metódust.
5. Végrehajtjuk az utasítást az Open vagy az ExecSQL metódussal.

A paraméterezés lehetőségeiről a következő fejezetben bővebben ejtünk szót.

A Prepare metódus használata nem kötelező. Kiadásakor az SQL Server megkapja a végrehajtandó utasítást előfeldolgozásra, ekkor értelmezi, optimalizálja, lefoglalja a végrehajtásához szükséges erőforrásokat. Ha lokális táblákkal dolgozunk, a BDE is megteszi ugyanezt. Így Open vagy ExecSQL hatására a query-k sokkal gyorsabban lefutnak. Ha nem hívjuk meg a Prepare-t, a Delphi a végrehajtás előtt automatikusan végrehajtja, majd utána végrehajt egy Unprepare-t is. Ha a Prepare-t explicit módon mi adjuk ki, akkor ez az optimalizációs fázis a szerveren csak egyszer fut le, és nem minden egyes alkalommal. A query minden további futtatásakor elegendő csak a paramétereit újraállítani és már lehet is futtatni. Ha már többet nem hívunk meg, mehet az Unprepare. Hogy egy query ilyen módon elő van-e készítve vagy sem, azt a Prepared boolean típusú property jelzi. Ha egy query SQL property-jét megváltoztatjuk, a komponens automatikusan kiad egy Close és egy UnPrepare utasítást.

A query-ben összeállított lekérdezésben hivatkozhatunk több adatbázis tábláira is. Ilyenkor heterogén lekérdezésről beszélünk. Egy heterogén lekérdezésben akár különböző szerverek, sőt különböző típusú szerverek tábláit is összekapcsolhatjuk. Ilyenkor az SQL utasítást a BDE dolgozza fel, ezért csak olyan parancsot adhatunk, amit a Local SQL is megért. Heterogén lekérdezést a normál lekérdezéshez nagyon hasonlóan csinálhatunk, egy-két apróságra kell csak odafigyelni.

1. Minden adatbázisnak, amire a query-ben hivatkozni fogunk, csináljunk BDE álnevet. A TQuery DatabaseName property-jét ne töltsük ki!
2. Az SQL utasítást írjuk be az SQL property-be. Minden táblanévre az adatbázis BDE álnevével hivatkozzunk, például ":SQLSrv:jobs". Az álnevet kettőspontok közé kell zárni, az egész hivatkozást pedig idézőjelek közé.
3. Innen már a megszokott sorrend szerint járhatunk el. Beállítjuk a paramétereket, ha vannak (Params), előkészítjük a lekérdezést (Prepare) és végrehajtjuk (Open vagy ExecSQL).

Ha például az Oracle1 álnevű Oracle adatbázisbeli Customer táblából és a Sybase1 álnevű Sybase adatbázisbeli Orders táblából szeretnénk egy lekérdezést, az SQL property-be a következőket kell beírni:
with SQL do
begin
  Clear;
  Add('SELECT Customer.CustNo, Orders.OrderNo ');
  Add('FROM ":Oracle1:CUSTOMER" JOIN ":Sybase1:ORDERS"');
  Add('  ON (Customer.CustNo = Orders.CustNo)');
  Add('  WHERE (Customer.CustNo = 1503)');
end;
Ha nem akarunk az álnevekkel bajlódni, használhatjuk a TDatabase komponenst is. Minden adatbázist kössünk TDatabase komponenshez, és nevezzük el őket a DatabaseName property-jükben. Az SQL utasításban az álnév helyett az így kiosztott neveket is felhasználhatjuk.

Az eredményhalmaz

Alapértelmezés szerint az eredményhalmaz csak olvasható, az adatmegjelenítési komponensekben megjeleníthetjük, de nem szerkeszthetjük. Ha mégis szeretnénk szerkeszteni, az eredményhalmazt "élővé" kell tennünk (live result set). Ez nagyon egyszerűen megy, a RequestLive propertry-t True-ra kell állítanunk. Ez még nem jelent azonban garanciát, a siker attól is függ, milyen lekérdezést állítunk össze. Egy lekérdezés akkor szerkeszthető:
  • ha nem tartalmaz DISTINCT kulcsszót,
  • joinokat,
  • összegző függvényeket (SUM, AVG),
  • beágyazott SELECT-et;
  • nem alapul eleve nem szerkeszthető táblákon
  • és az ORDER BY záradéka indexelt mezőre hivatkozik.


Ha a fenti feltételek teljesülnek, és a RequestLive property-jében True lekérdezés szerkeszthető eredményhalmazt ad vissza, a CanModify property értéke True-ra változik. Ha a SELECT nem alkalmas szerkeszthető eredményhalmaz produkálására, dBase és Paradox táblák esetében nem szerkeszthető eredményhalmazt kapunk vissza, távoli adatbázisszerver esetén valami hibakódot kapunk.

Nem szerkeszthető eredményhalmazt az úgynevezett cached update technikával módosíthatunk. Ehhez a query CachedUpdate property-jét True-ra kell állítanunk és a TCachedUpdate komponens ModifySQL, InsertSQL vagy DeleteSQL property-jén keresztül kell érvényesítenünk a változtatást végrehajtó SQL utasításunkat. Ezzel a témával egy későbbi fejezetben részletesen foglalkozunk majd.

Optimalizációs tippek

Ha egy lekérdezést többször is végrehajtunk, hívjuk meg a Prepare metódust az első végrehajtás előtt.

Amikor egy lekérdezést végrehajtva visszakapunk egy eredményhalmazt, egy pointer mutat annak első rekordjára. Ez a pointer mutatja meg azt is, hogy a vizuális objektumok éppen melyik rekordot mutatják. A pointer az adathalmazon előre és hátra is képes mozogni, ennek megfelelően a query objektumnak időt és tárkapacitást kell felhasználnia ennek adminisztrálására. Felgyorsíthatjuk a query-t, ha megelégszünk azzal, hogy a pointer csak előrefelé tud végiglépkedni a rekordokon. Ehhez az UniDirectional property-t kell True-ra állítanunk. Alapértelmezés szerint értéke False. A beállítást még a Prepare meghívása előtt kell megtennünk:
Query1.UniDirectional := True;
Query1.Prepare;
Query1.Open;

MS SQL cikksorozat

MS SQL adatbázis kezelés Delphi-ből - 1. rész
MS SQL adatbázis kezelés Delphi-ből - 2. rész
MS SQL adatbázis kezelés Delphi-ből - 3. rész
MS SQL adatbázis kezelés Delphi-ből - 4. rész
MS SQL adatbázis kezelés Delphi-ből - 5. rész
MS SQL adatbázis kezelés Delphi-ből - 6. rész
MS SQL adatbázis kezelés Delphi-ből - 7. rész
MS SQL adatbázis kezelés Delphi-ből - 8. rész

MS SQL adatbázis kezelés Delphi-ből - 9. rész

MS SQL adatbázis kezelés Delphi-ből - 10. rész
MS SQL adatbázis kezelés Delphi-ből - 11. rész
MS SQL adatbázis kezelés Delphi-ből - 12. rész
MS SQL adatbázis kezelés Delphi-ből - 13. rész
MS SQL adatbázis kezelés Delphi-ből - 14. rész
MS SQL adatbázis kezelés Delphi-ből - 15. rész
MS SQL adatbázis kezelés Delphi-ből - 16. rész
MS SQL adatbázis kezelés Delphi-ből - 17. rész
MS SQL adatbázis kezelés Delphi-ből - 18. rész
MS SQL adatbázis kezelés Delphi-ből - 19. rész
MS SQL adatbázis kezelés Delphi-ből - 20. rész
MS SQL adatbázis kezelés Delphi-ből - 21. rész
MS SQL adatbázis kezelés Delphi-ből - 22. rész
MS SQL adatbázis kezelés Delphi-ből - 23. rész
MS SQL adatbázis kezelés Delphi-ből - 24. rész
MS SQL adatbázis kezelés Delphi-ből - 25. rész
MS SQL adatbázis kezelés Delphi-ből - 26. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 27. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 28. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 29. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 30. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 31. rész
MS SQL adatbázis kezelés Delphi-ből - MS SQL 32. rész