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

20. rész

forráskód letöltése
Adatbázis kezelő alkalmazásban gyakran van szükség arra, hogy egy lekérdezés eredményét mondjuk TDBGrid-ben mutassuk meg, a felhasználó igényei szerint szűrve. Ilyenkor egy TQuery komponenst szoktunk használni egy SELECT utasítással, és a szűrést a WHERE feltételen keresztül valósítjuk meg. A felhasználónak általában teljes szabadsága van a szűrés beállításában, lekérhet egy nagyon szűk részhalmazt, de lekérheti a teljes tábla vagy nézet tartalmát is. Mellékelt példában a nagy eredményhalmazok kezelésének nézünk utána. A példaprogram futtatásához a pubs adatbázisban hozzunk létre egy táblát largeset néven (futtassuk le az SQL Serverben a mellékelt CreateTable.sql scriptet). A programban feltöltjük ezt a táblát 3000 teszt rekorddal, ehhez a 'tábla feltöltése adattal' gombot kell megnyomni. A gomb ismételt megnyomásával újabb 3000 adat íródik a táblába. Végül a táblát egy query-n keresztül kérdezzük le egy TDBGrid-be, miközben két szöveges mezőn keresztül szűrhetünk. Alaphelyzetben azokat a rekordokat listázzuk ki, amelyek s1 sztringje 'a'-val, s2 sztringje 'b'-vel kezdődik.
select i1, i2, i3, s1, s2, s3 
  from largeset 
  where s1 like ' a%' and s2 like ' b%'
Ilyen valószínűleg kevés van, tehát a megjelenítés egész gyors lesz. Próbáljuk ki, hogy a TEdit komponensekbe a %a%, illetve a %b% szövegeket írjuk.

A felhasználónak azonban lehetősége van a szűrést úgy beállítani, hogy minden rekord lejöjjön. Első körben ez nem is jelent problémát, mert a BDE van annyira okos, hogy az SQL Servertől csak annyi adatot kér el, amennyit éppen meg kell jelenítenie. Ha úgy nyitunk meg egy query-t, hogy nem jelenítjük meg, akkor egyetlen rekord sem jön át a query megnyitásakor! Ahogy a TDBGrid-ben lefelé mozgunk, mindig annyi rekordot kapunk az SQL Servertől, amennyi éppen a TDBGrid-nek kell.

Érdemes az SQLMonitort is bekapcsolni, és figyelni, hogy mi történik. A letöltött rekordokat a BDE puffereli, és ha a TDBGrid-ben visszafelé mozgunk, már nem kell a szerverhez fordulni.
A módszerrel akkor van probléma, ha a felhasználó az utolsó rekordokat szeretné látni, és Ctrl-End-et nyom. Ekkor ugyanis a BDE az összes rekordot lehozza. Ez már a 3000 rekordos példatáblánk esetén is eltart egy ideig, így nem nehéz elképzelni, hogy mennyit kéne várni egy milliós nagyságrendű rekordot tartalmazó tábla esetén. Ha a BDE nekiáll letölteni az összes rekordot, már nincs módunk a folyamat megállítására, mindenképpen végig kell várnunk. A nagyszámú rekord pufferelése miatt a nem annyira biztonságos Windows9x rendszerek akár be is dobhatják a törölközőt.

Ugyanez a gond, ha a felhasználó a scrollbart lefelé húzza. Ne felejtsük el, hogy query esetében a Delphi nem tudja kitalálni, hogy az eredményhalmazban mennyi rekord lesz, így a TDBGrid scrollbárjának csak három állapota van, a halmaz elején áll, valahol középen és a halmaz végén.

A harmadik veszélyes szituáció a TQuery recordcount metódusának meghívása. Ekkor ugyanis a BDE lekéri az összes rekordot és maga számolja azokat össze!

A példaprogramban ezt is ki lehet próbálni. A státuszsor frissítésére szolgáló metódus tartalma:
  sb1.SimpleText := 'Rekordok száma: ' + inttostr(q1.Recordcount);
Ez minden lekérdezés indítása után meghívódik, hogy a felhasználó lássa, hogy mekkora eredményhalmazt produkált. Ha minden rekordot lekérünk (where s1 like '%' and s2 like '%'), akkor a recordcount hívása miatt lassú lesz a lekérdezésünk, míg ha ezt a sort kikommentezzük, akkor csak a TDBGrid kitöltéséhez szükséges rekordok jönnek le teljes halmaz lekérdezésekor is.

A TTable komponens használatakor más a helyzet. (A 16 bites Delphiben még nem, de a 2.0-tól kezdve már igen.) Ha a TTable RecordCount metódusát hívjuk, egy select count(*) query megy az SQL Servernek. Ugyan most is össze kell számolni a rekordokat, de a szerver ezt nagyságrendekkel gyorsabban képes elvégezni, mint a BDE. Ha böngészés során Ctrl-End-et nyomunk, a BDE valahogy képes a tábla végére ugrani, és az utolsó néhány rekordot elkérni. A rekordok azonban nem pufferelődnek, ahogy le-föl mozgunk a TDBGrid-ben, a BDE folyamatosan fetch-eli a megjelenítendő rekordokat.

Szerencsére a problémákra több megoldás is létezik.


TOP

Ha a BDE-t úgy paramétereztük, hogy az SQL query-ket ne ő, hanem az SQL Server hatjsa végre, akkor használhatjuk a SELECT utasítás TOP kulcsszavát.
SELECT TOP n [PERCENT] ...
Az n szám megadásával meghatározhatjuk, hogy az eredményhalmaz első hány rekordjára vagyunk kíváncsiak. Ha a PERCENT szót is kiírjuk, akkor az n nem a sorok számát, hanem az eredményhalmaz százalékban kifejezett hányadát jelenti.
select TOP 100 *
  from largeset
Az eredményhalmaz első 100 sorát kérjük le.
select TOP 10 PERCENT *
  from largeset
Az eredményhalmaz 10%-t kérjük el a szervertől.

Ha a SELECT utasításban az ORDER BY-t is használjuk, a TOP kulcsszó a már rendezett halmazon jut érvényre. Ilyenkor az SQL Server a teljes eredményhalmazt előállítja, rendezi, és utána leszámolja a megfelelő számú rekordot.


SET ROWCOUNT

Egy másik korlátozási módszer az SQL Server oldalán a SET ROWCOUNT n utasítás használata. Az utasítással azt adhatjuk meg, hogy legfeljebb hány soros lekérdezésekkel dolgozhat a szerver. Hatása ugyanaz, mint a TOP kulcsszóé, de egy kicsit másképp működik.


Ha ORDER BY-t használunk egy SELECT-ben, a SET ROWCOUNT n hatására csak n rekord válogatódik le, és az rendeződik sorba, vagyis a korlátozás hatása meg az ORDER BY kiértékelése előtt érvényesül. Továbbá amíg a TOP kulcsszó csak egy SELECT-re vonatkozik, addig a SET ROWCOUNT hatása addig tart, amíg egy másik SET ROWCOUNT utasítás azt felül nem bírálja. A korlátozást a SET ROWCOUNT 0 utasítással kapcsolhatjuk ki.


Max Rows

A BDE Administrator programban az SQL Links jellemzői között találjuk a Max Rows-t. Itt megadhatjuk, hogy az SQL utasítások végrehajtása során az SQL driver legfeljebb hány sort fetch-elhet le. Ez nemcsak a táblákra és nézetekre vonatkozik, hanem a sémainformációkra is, tehát túl kis értéket nem szerencsés beállítani.

Ha a lekérdezés eredménye több rekordból áll, mint a Max Rows értéke, az utolsó rekordnál a DBIERR_ROWFETCHLIMIT hibaüzenet generálódik. Ez ugyanaz, mint a DBIERR_EOF üzenet, de mégis jelzi, hogy egy kliens által kikényszerített fájlvége jelről van szó. A Delphi komponensei úgy fognak viselkedni, mintha az eredményhalmazban nem lenne több rekord.


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