Objekt Recordset
Doc. Dr. Vladimír Homola, Ph.D.
Objekt třídy Recordset je jediným objektem umožňujícím přístup k datům. Jde vlastně o řádky ("datový obsah") tabulky relační databáze nebo výsledek dotazu - příkazu Select z SQL. Databáze v Microsoft Jet obsahují obecně tabulek a dotazů více; otevřené objekty Recordset jsou obsahem kolekce Recordsets objektu Database.
Použití objektu Recordset je podmíněno dostupností knihovny DLL, ve které je definován. V prostředí Visual Basic se tak učiní pomocí menu položky References... - ta je umístěna v hlavním menu Project v případě samostatného překladače Basicu, nebo v hlavním menu Tools v případě volání Visual Basicu z aplikace (Excelu, Accessu, Wordu atd.). Z nabídek knihoven se volí ta, která začíná DAO. Připojená čísla označují verzi, volí se podle potřeby (většinou ta nejvyšší). Verze znamenají "stupeň vývoje" struktury databáze Microsoftu (MDB): např. program Access dodávaný s Office 97 používá DAO350.DLL, Access dodávaný s Office 2000 používá DAO360.DLL.
Tyto knihovny obsahují DAO příslušné verze objektových modelů. DAO (Data Access Objects - objekty pro přístup k datům) je množina objektů, které umožňují klientům automatizace OLE programově přistupovat k datům a modifikovat zdroje dat. Jsou použity v programech Access, Visual Basic - obecně ve všech aplikacích, které zpracovávají data uložená jako Microsoft Jet databáze. Dále je možno zpracovávat všechny formáty, které Microsoft Jet podporují (jako např. zdroje dat v ODBC včetně SQL serveru, FoxPro, Paradoxu aj.).
Protože článek je zaměřen k poskytnutí základních informací pro tvorbu jednoduchých aplikací, jsou uvedeny jen nejpoužívanější metody a vlastnosti.
Objekt Recordset zpřístupňuje datové zdroje ve tvaru tabulky relační databáze - množiny řádků, sestávajících z datových polí. V každém okamžiku má aplikace k disposici jeden jediný konkrétní řádek, s jehož daty může pracovat - tzv. aktuální řádek (záznam). Pro účely označení aktuálního řádku zavádí databázové systémy pojem pointer (ukazatel, "ukazovátko") na aktuální řádek ve zřejmém významu.
Nechť rs je identifikátorem konkrétního otevřeného objektu Recordset, např. tabulky VYDAJE databáze DOMACOST:
Dim db As Database, rs As Recordset
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
Set rs = db.OpenRecordset("VYDAJE")
Pro pohyb v tabulce slouží metody MoveXY (viz níže) - umožní nastavit kterýkoliv řádek jako aktuální. Nechť tedy je nyní nějaký řádek aktuálním řádkem, nechť tabulka VYDAJE má sloupec např. CENA. Přístup k hodnotě ceny aktuálního řádku zajistí zápis tvaru
rs ! CENA
(operátorem výběru pole je vykřičník, nikoliv tečka!). Zápis lze použít především ve výraze, kde znamená skutečně hodnotu typu odpovídající typu pole CENA. Zápis lze použít i na levé straně přiřazovacího příkazu, např.
rs ! CENA = 12.60
kde znamená odkaz na pole. O změnách dat v tabulce však viz metody Edit a AddNew.
Kolekce obsahuje jednotlivé objekty třídy Field (datové pole), z nichž sestává tabulka dat reprezentovaná daným objektem Recordset. Blíže jsou datová pole popsána zde.
Metody MoveFirst, MoveLast, MoveNext, MovePrevious posunou ukazatelem aktuálního řádku na první (MoveFirst), poslední (MoveLast), následující (MoveNext) a předchozí (MovePrevious) záznam v tabulce; tento záznam se stává aktuálním záznamem. Metody mají syntaxi
rs.MoveFirst
rs.MoveLast
rs.MoveNext
rs.MovePrevious
kde rs je identifikátor daného objektu Recordset. Metoda Move má syntaxi
rs.Move n
kde rs je identifikátor daného objektu Recordset a n je výraz typu Long. Metoda Move posune ukazatel aktuálního řádku o n řádků dopředu (směrem ke konci tabulky) v případě kladného n, nebo o n pozic zpět (směrem k začátky tabulky) v případě záporného n.
Ukazatel aktuálního řádku má dvě specielní posice neukazující na žádný konkrétní řádek. Jejich existenci si vynutily metody MoveNext a MovePrevious:
Jestliže ukazatel aktuálního řádku ukazuje na poslední řádek tabulky, metoda MoveNext ho posune za poslední řádek na posici označovanou jako EOF (End Of File - konec souboru). Na této posici nejsou žádná použitelná data. Jakmile se dostane ukazatel na tuto posici, je to indikováno hodnotou True ve vlastnosti EOF objektu Recordset. Aplikace podle této vlastnosti poznají, že "dál už nic není".
Jestliže ukazatel aktuálního řádku ukazuje na první řádek tabulky, metoda MovePrevious ho posune před první řádek na posici označovanou jako BOF (Begin Of File - začátek souboru). Na této posici nejsou žádná použitelná data. Jakmile se dostane ukazatel na tuto posici, je to indikováno hodnotou True ve vlastnosti BOF objektu Recordset. Aplikace podle této vlastnosti poznají, že "vpředu už nic není".
Volání metody Move s takovým počtem, který přesahuje počet zbývajících řádků (ale ukazatel ještě není na EOF), umístí ukazatel na EOF. Volání metody Move s takovým počtem, který přesahuje počet předcházejících řádků (ale ukazatel ještě není na BOF), umístí ukazatel na BOF.
Volání metody MoveNext nebo Move s kladným počtem v posici EOF, a metody MovePrevious nebo Move se záporným počtem v pozici BOF vede k chybě.
Jestliže je množina řádků prázdná (tabulka neobsahuje žádná data), je vlastnost EOF i BOF nastavena na True a pokud ukazatelem metodami Move vede k chybě.
Metody slouží pro změnu údajů (Edit) aktuálního řádku a pro přidání (AddNew) nového řádku.
Pro provádění změn v tabulce relační databáze vytváří databázový stroj při otevření objektu Recordset v operační paměti dočasný paměťový prostor (tzv. buffer) o velikosti jednoho řádku dané tabulky. Paměťový buffer si lze představit jako jednorozměrné pole typu Variant obsahující po řadě jednotlivá pole řádku tabulky - to je důležité z hlediska typu údajů.
Metoda Edit má syntaxi
rs.Edit
a zapíše hodnoty aktuálního řádku do paměťového bufferu. Paměťový buffer a aktuální řádek budou tedy obsahovat stejné hodnoty.
Metoda AddNew má syntaxi
rs.AddNew
a pracuje takto: nejprve přidá na konec tabulky dat representované objektem Recordset nový řádek a učiní tento řádek aktuálním řádkem. Současně naplní všechna jeho pole hodnotami Null. Potom zapíše hodnoty aktuálního řádku (tohoto nově přidaného) do paměťového bufferu. Paměťový buffer a aktuální řádek budou tedy obsahovat stejné hodnoty - samé Null.
Po provedení metody Edit nebo AddNew se dočasně mění význam zápisu pro přístup k datovému poli. Nechť má otevřená tabulka pole CENA . Pak zápis
rs ! CENA
neznamená přímo pole tabulky, ale pole paměťového bufferu. Přiřazení
rs ! CENA = 12.60
tedy přiřazuje dvanáct šedesát nikoliv do tabulky, ale do paměťového bufferu.
Zápis obsahu paměťového bufferu zpět do tabulky dat provede metoda Update. Její syntax je
rs.Update
Jestliže po změnách provedených po volání metod Edit nebo AddNew nenásleduje volání metody Update, změny se v tabulce neprojeví. Zvláště volání jakékoliv metody mající za následek změnu aktuálního řádku (např. Move) maže obsah paměťového bufferu - pokud tedy nebyl dříve zapsán metodou Update do tabulky, zůstává řádek tabulky beze změny.
Metoda CancelUpdate má syntaxi
rs.CancelUpdate
a zruší všechny změny započaté metodou Edit a ještě neprovedené metodou Update. Má tedy stejný účinek jako např. posunutí ukazatele na jiný řádek (až na to, že se aktuální řádek nemění). Analogicky to platí i o AddNew, ale nově přidaný řádek se neodstraní, jen zůstane prázdný.
Příklad na změnu ceny podle předchozího výkladu:
Dim db As Database, rs As Recordset
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
Set rs = db.OpenRecordset("VYDAJE")
rs.Edit
rs ! CENA = 12.60
rs.Update
Metoda vypustí aktuální řádek. Má syntaxi
rs.Delete
kde rs je identifikátor daného objektu Recordset. Objekt Recordset musí být aktualizovatelný objekt, např. tabulka relační databáze. Před voláním musí být nějaký řádek aktuálním řádkem (ukazatel nesmí být na BOF nebo EOF). Po volání metody Delete zůstává vypuštěný řádek aktuálním, ale je označen jako vypuštěný a nelze jej editovat. Po přemístění ukazatele (např. metodou Move) se vypuštěný řádek opustí a už nikdy nelze učinit aktuálním - tváří se to, jako kdyby tam nebyl.
Metoda vyhledá v indexované tabulce (otevřený Recordset typu tabulka) záznam, jehož index splňuje jistá kriteria, a tento záznam učiní aktuálním záznamem.
Metoda má syntaxi
rs.Seek cmp, k1, k2, ..., k13
Značí přitom
rs - identifikátor otevřeného objektu Recordset, v jehož tabulce se hledá; objekt musí mít přiřazený libovolný ze svých indexů, podle jeho hodnot se pak hledá
cmp - výraz typu string, který musí být jeden z pěti: "<", ">", "<=", ">=" nebo "=".
k1 - povinný výraz stejného typu, jako je (první) pole nastaveného indexu
k2 až max. k13 - nepovinných dalších až 12 výrazů stejného typu jako jsou (další) pole nastaveného indexu.
Příklad vyhledání prvního řádku s cenou větší než 12.60, je-li tabulka VYDAJE databáze DOMACNOST indexována podle sloupce CENA a index se jmenuje XCENA:
Dim db As Database, rs As Recordset
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
Set rs = db.OpenRecordset("VYDAJE")
rs.Index = "XCENA"
rs.Seek ">", 12.60
Jestliže v tabulce existuje řádek, jehož cena je větší než 12.60, stává se aktuálním řádkem. Je-li takových řádků více, aktuálním řádkem se stává první takový řádek (počítáno "seshora").
Řádek vyhovující dané podmínce nemusí existovat. Proto má objekt Recordset vlastnost NoMatch (nevyhovuje) typu Boolean (logická hodnota), která obsahuje indikaci výsledku předchozí metody Seek. Jestliže žádný záznam vyhovující podmínce nebyl nalezen, je hodnota vlastnosti NoMatch rovna True (pravda) a poloha ukazatele na aktuální řádek není definována. Jestliže řádek vyhovující podmínce byl nalezen, je hodnota NoMatch rovna False a ukazatel aktuálního řádku obsahuje nalezený řádek.
Jestliže je operátor porovnání ">", ">=" nebo "=", pak metoda Seek prohledává index od začátku. Je-li operátor porovnání "<" nebo "<=", pak metoda Seek prohledává index od konce.
Metodou se vynutí aktualizace množiny dat, která tvoří zdroj dat objektu Recordset. Jestliže např. Recordset je výsledkem dotazu - příkazu Select z SQL čerpajícího ze zdrojové tabulky, v níž došlo ke změně, neodpovídají data objektu Recordset aktuálnímu stavu. Musí se tedy použít metoda, jejíž syntaxe je
rs.Requery
kde rs je daný objekt Recordset. Po jejím volání se aktuálním řádkem stává první řádek, nebo je BOF i EOF nastaveno na True, jestliže obnovená data neobsahují ani jeden řádek
Metoda zavře otevřený objekt Recordset. Má syntaxi
rs.Close
kde rs je identifikátor otevřeného objektu třídy Recordset.
Jestliže před použitím metody Close byla metodou Edit započata aktualizace dat v aktuálním řádku, ale nebula metodou Update dokončena, změny se v tabulce dat neprovedou.
Viz metody Move.
Hodnota typu Long, která lze pouze číst. Je rovna jedné z pojmenovaných konstant:
dbEditNone - žádná editační metoda (Edit, AddNew) není započata
DbEditInProgress - je rozpracována metoda Edit, kopie aktuálního řádku je v paměťovém bufferu (který už možná má změněné hodnoty)
dbEditAdd - je rozpracována metoda AddNew, aktuálním řádkem je nově přidaný prázdný řádek, jehož hodnoty jsou v paměťovém bufferu (ale který už možná je změněný)
Vlastnost je typu String a obsahuje buď prázdnou hodnotu nebo jméno indexu, který řídí zpracování. Lze použít jen u objektů Recordset typu tabulka relační databáze (tedy nikoliv u výsledku dotazu).
Vlastnost typu Long obsahující počet řádků (=záznamů) zpřístupněných daným objektem Recordset typu tabulka relační databáze, nebo již zpracovaných u objektu Recordset.
U objektů Recordset typu výsledek dotazu se celkový počet řádků objeví, až když se řádky projdou všechny - přesněji až se ukazatel dostane nakonec. o lze nejjednodušeji zajistit posloupností volání metod
rs.MoveLast
rs.MoveFirst
Orig. 4 / 1999
Rev. 07 / 2002