13. Databázové aplikace I
  1. V této a další kapitole je uveden stručný úvod do programování databázových aplikací v C++ Builderu. Databáze jsou data uložená ve formátu tabulek. Tabulky obsahují položky jako Přijmení, Jméno, Adresa apod. Tyto položky tvoří jednotlivé záznamy databáze. Termín databáze je použit k označení celého systému vytváření a údržby dat. Databáze může být jedna jednoduchá tabulka nebo také stovky tabulek s miliony záznamů. Tabulky mohou obsahovat jeden nebo více indexů. SQL databáze také mohou obsahovat dotazy a uložené procedury. Vidíme, že databáze je více než jen tabulka s daty.

  2. Tabulka se skládá z položek a záznamů. Položky jsou jednotlivé kategorie dat v tabulce. Např. tabulka obsahující adresář bude obsahovat položky Příjmení, Jméno, Adresa, Telefonní číslo apod. Položky také někdy označujeme jako sloupce. Záznamy jsou kompletní informace o jednotlivých osobách. Záznamům také někdy říkáme řádky. Databáze používá ukazatel na aktuální řádek databáze. Tomuto ukazateli říkáme kurzor. Kurzor ukazuje na řádek, který čteme nebo editujeme. Kurzor se přesouvá při prohlížení databáze, vkládání záznamů, rušení záznamů apod. Když říkáme, že kurzor je ukazatel, pak to neznamená, že se jedná o ukazatel ve smyslu C++. Je to pouze indikátor pozice aktuálního záznamu.
    Kolekce dat vracená databází se nazývá datová množina. Datová množina může být více než pouhá data obsažená v tabulce. Může to být výsledek dotazu kombinující data z mnoha tabulek. Např. můžeme mít databázi obsahující jména a adresy svých zákazníků, jejich objednávek a řádků objednávek. Tato data mohou být obsažena v tabulkách Zákazník, Objednávka a Řádek objednávky. Můžeme mít požadavek na zjištění detailů o deseti posledních objednávkách jistého zákazníka. Je tedy nutno získat informace ze všech těchto tabulek. I když data pocházejí z několika různých tabulek, stále jsou prezentovány jako jedna datová množina.
    Nejjednodušší typ databáze je lokální databáze. Lokální databáze je databáze, která je umístěna pouze na jednom počítači. Předpokládejme, že potřebujeme ukládat seznam jmen a adres. Můžeme vytvořit lokální databázi k uložení těchto dat. Tato databáze se pravděpodobně bude skládat z jedné tabulky. K této tabulce budeme přistupovat pouze naším programem. Všechny provedené změny budou zapsány přímo do této tabulky. Databáze Paradox, dBASE a Access jsou obvykle lokálními databázemi.
    Jsou také databáze typu klient/server. Tyto databáze jsou uloženy a udržovány na počítači serveru a může k nim přistupovat jeden nebo více uživatelů (klientů). Používání tohoto typu databází je prováděno prostřednictvím sítě. Protože uživatelů bývá obvykle více, může se jich najednou pokusit více o přístup k databázi. Tím vznikají problémy souběžného databázového přístupu. Uživatel tohoto typu databáze nikdy nepracuje s databází přímo. Přistupuje k databázi pomocí aplikace spuštěné na lokálním počítači. Tyto aplikace (nazvané klientské aplikace) zajišťují dodržování jistých pravidel a nedovolí udělat nic, co by databáze nedokázala zpracovat.
    Lokální databáze jsou také nazývány jednovrstvové databáze. Jednovrstvová databáze je databáze, ve které všechny změny (jako je editace dat, vkládání záznamů nebo rušení záznamů) jsou provedeny bezprostředně. Program má přímé připojení k databázi. U dvouvrstvových databází, klientská aplikace pracuje s databázovým serverem prostřednictvím databázových ovladačů. Databázový server je zodpovědný za vytvoření připojení. Klientská aplikace odpovídá za to, že do databáze budou zapsány správné informace.
    Ve vícevrstvové architektuře klient/server, klientská aplikace využívá aplikační služby databázového serveru. Tyto programy střední vrstvy se nazývají serverovské aplikace, protože slouží klientským aplikacím. Jedna aplikace může zodpovídat za zpracování datových požadavků klientů a jejich předání serveru. Jiná aplikace může zajišťovat bezpečnost dat. Klientské aplikace běží na lokálních počítačích, serverové aplikace obvykle na serveru a samotná databáze může být i na jiném serveru. Idea vícevrstvové architektury je, že klientské aplikace mohou být velmi malé, protože většinu práce provedou serverové aplikace. To umožňuje vytvářet aplikace, které nazýváme tenký klient.
    Jiný důvod k použití vícevrstvové architektury je správa programovacích zdrojů. Klientské aplikace mohou být vytvářeny méně zkušenými pracovníky, protože tyto aplikace pracují se serverovými aplikacemi, které řídí přístup k samotné databázi. Serverové aplikace vytvářejí zkušení programátoři, kteří znají pravidla se kterými databáze musí pracovat a musí také zajistit bezpečnost dat.
  3. K umožnění přístupu k databázím, C++ Builder poskytuje BDE (Borland Database Engine). BDE je kolekce DLL a ovladačů, které umožňují přistupovat k různým databázím. Ovladače BDE překládají databázové příkazy vyšší úrovně (jako Open nebo Post) na příkazy jistého typu databáze. To umožňuje naší aplikací připojit se k nějakému typu databáze a to bez nutnosti vědět, jak tato databáze pracuje.

  4. Ovladače, které jsou nainstalovány na našem počítači, závisí na verzi C++ Builderu, kterou vlastníme. Všechny verze umožňují připojení k databázím Paradoxu a dBASE. Tento ovladač nazvaný STANDARD umožňuje pracovat s lokálními databázemi. Vyšší verze umožňují pracovat s dalšími databázemi.
    BDE používá pro přístup k jisté databázi přezdívku. Přezdívka BDE je množina parametrů, které popisují databázové připojení.
    K zobrazení seznamu existujících přezdívek provedeme tyto kroky: začneme vývoj nové aplikace a na formulář umístíme komponentu Table (je na stránce DataAccess Palety komponent). Seznam přezdívek je uveden v rozbalovacím seznamu vlastnosti DatabaseName této komponenty. Když vybereme nějakou přezdívku, pak v rozbalovacím seznamu vlastnosti TableName vidíme dostupné tabulky.
    Verze Client/Server C++ Builderu poskytuje mimo BDE i SQL Links. Jedná se o kolekci dalších ovladačů. Tyto ovladače umožňují aplikacím C++ Builderu přímé připojení k databázím firem Oracle, InterBase, Informix, Sybase a Microsoft.
  5. Nyní se pokusíme vytvořit jednoduchou databázovou aplikaci. Nejprve si ale něco řekneme o databázových komponentách VCL. Databázové komponenty je možno rozdělit do dvou skupin: na nevizuální komponenty datového přístupu a na vizuální datové komponenty. Nevizuální komponenty datového přístupu poskytují mechanismus umožňující získávat data (jsou na stránce DataAccess Palety komponent) a vizuální datové komponenty umožňují prohlížet a editovat tato data (jsou na stránce Data Controls). Komponenty datového přístupu jsou odvozeny od TDataSet a zahrnují třídy TTable, TQuery a TStoredProc. Mezi vizuální komponenty patří TDBEdit, TDBListBox, TDBGrid a další. Tyto komponenty pracují jako standardní TEdit, TListBox, atd. s tou odchylkou, že jsou spojeny s jistou tabulkou nebo položkou v tabulce. Editací těchto komponent editujeme také připojenou databázi.

  6. Použití těchto komponent si nyní ukážeme na příkladu. Budeme potřebovat nějaký databázový soubor (v následujících zadáních budou potřeba další soubory). Stáhneme si je. Jak již víme vlastnost DatabaseName je určena k volbě přezdívky BDE. Pro lokální databáze je vhodnější místo výběru přezdívky, zadat zde přímo adresář, ve kterém jsou databázové soubory uloženy. Rozbalovací seznam vlastnosti TableName pak obsahuje seznam databázových souborů v tomto adresáři.
    Začneme vývoj nové aplikace. Na formulář umístíme komponentu Table a změníme její vlastnost DatabaseName na adresář, do kterého jsme uložili stažené soubory a vlastnost TableName na ANIMALS.DBF. Na formulář dále umístíme komponentu DataSource a nastavíme její vlastnost DataSet na Table1 (vybereme v rozbalovacím seznamu). Datový zdroj je nyní spojen s datovou množinou Table1. Na formulář také přidáme komponentu DBGrid a změníme její vlastnost DataSource na DataSource1. Tím je mřížka připojena k datovému zdroji a tedy nepřímo k datové množině. U komponenty Table nyní změníme vlastnost Active na true a data máme zobrazena v tabulce.
    Na formulář přidáme ještě komponentu DBImage, změníme její vlastnost DataSource na DataSource1 a vlastnost DataField na BMP (tato položka tabulky Animals.DBF obsahuje obrázek). Na formulář umístíme komponentu DBNavigator a nastavíme vlastnost DataSource na DataSource1.
    Nyní již program můžeme spustit a pomocí tlačítek Navigátora procházet záznamy tabulky. To vše bez zápisu řádku kódu. Komponenty datového přístupu jsou použity pro připojení k databázi a k jisté tabulce v databázi. Komponenta Table je použita pro přístup k databázové tabulce. Je to nejjednodušší způsob zpřístupnění dat v tabulce. Komponenta Query zpřístupňuje data tabulek pomocí příkazů SQL. Komponenta StoredProc umožňuje zpřístupnit databázi prostřednictvím uložených procedur. Uložená procedura je kolekce databázových příkazů, které provádějí jednu nebo více akcí v databázi. Uložené procedury se obvykle používají pro řadu databázových příkazů, které se často opakují.
  7. TDataSet je předchůdce tříd TTable, TQuery a TStoredProc. Většina vlastností, metod a událostí těchto tříd je definována v TDataSet. Základní vlastnosti TDataSet jsou popsány v následující tabulce:

  8.  
    Vlastnost Popis
    Active Otevírá datovou množinu při nastavení na true a uzavírá ji při nastavení na false.
    AutoCalcFields Určuje zda jsou vypočítávány počitatelné položky.
    Bof Vrací true, pokud kurzor je na prvním záznamu v datové množině a false není-li.
    CachedUpdates Při nastavení na true, aktualizace jsou drženy ve vyrovnávací paměti na klientským počítači dokud celá transakce není kompletní. Při nastavení na false jsou všechny změny zapisovány ihned do databáze.
    CanModify Určuje, zda uživatel může modifikovat data v datové množině.
    DataSource Komponenta DataSource přiřazená k této datové množině.
    DatabaseName Jméno současně používané databáze.
    Eof Vrací true, pokud kurzor je na posledním záznamu a false není-li.
    FieldCount Počet položek v datové množině. Protože datová množina může být dynamická (např. výsledek dotazu), počet položek se může měnit.
    Fields Pole objektů TFields, které obsahují informace o položkách v datové množině.
    FieldValues Vrací hodnotu specifikované položky současného záznamu. Jedná se o datový typ Variant.
    Filter Výraz určující, které záznamy má datová množina obsahovat.
    Filtered Při nastavení na true datová množina je filtrována.
    FilterOptions Určuje, jak je filtr použit.
    Found Určuje zda operace Find je úspěšná.
    Handle Madlo kurzoru BDE datové množiny. Používá se pouze při přímém volání BDE.
    Modified Indikuje, zda současný záznam byl modifikován.
    RecNo Číslo současného záznamu v datové množině.
    RecordCount Vrací počet záznamů v datové množině.
    State Vrací současný stav datové množiny (dsEdit, dsBrowse, dsInsert apod.).
    UpdateObject Určuje komponentu TUpdateObject používanou pro odložené aktualizace.
    UpdatesPending Je-li true, pak vyrovnávací paměť odložených aktualizací obsahuje změny, které nejsou aplikovány na datovou množinu.

    Další tabulka obsahuje popis základních metod TDataSet.
     

    Metoda Popis
    Append Vytváří prázdný záznam a přidává jej na konec datové množiny.
    AppendRecord Přidává záznam s danými daty na konec datové množiny.
    ApplyUpdates Povoluje databázi aplikovat odložené aktualizace. Aktualizace nejsou zapsány, pokud není volána metoda CommitUpdates.
    Cancel Zruší všechny změny provedené v současném záznamu.
    CancelUpdates Zruší odložené aktualizace.
    ClearFields Zruší obsah všech položek současného záznamu.
    CommitUpdates Aplikuje odložené aktualizace a vyprázdní vyrovnávací paměť odložených aktualizací.
    Close Uzavírá datovou množinu.
    Delete Ruší současný záznam.
    DisableControls Zakazuje vstup do datových ovladačů přiřazených k datové množině.
    Edit Povoluje editaci současného záznamu.
    EnableControls Povoluje vstup do datových ovladačů přiřazených k datové množině.
    FetchAll Získává všechny záznamy od kurzoru do konce datové množiny a ukládá je lokálně.
    FieldByName Vrací ukazatel TField na jméno položky.
    FindFirst Hledá první záznam odpovídající filtrovacím kritériím.
    FindNext Hledá další záznam odpovídající filtrovacím kritériím.
    FindLast Hledá poslední záznam odpovídající filtrovacím kritériím.
    FindPrior Hledá předcházející záznam odpovídající filtrovacím kritériím.
    FreeBookmark Ruší dříve nastavené záložky pomocí GetBookmark a uvolňuje paměť alokovanou pro záložky.
    GetBookmark Nastavuje záložku na současný záznam.
    GetFieldNames Získává seznam jmen položek v datové množině.
    GotoBookmark Umísťuje kurzor na záznam určený specifikovanou záložkou.
    Insert Vkládá záznam a uvádí datovou množinu do editačního režimu.
    InsertRecord Vkládá záznam s danými daty do datové množiny.
    Last Přesouvá ukazatel na poslední záznam v datové množině.
    Locate Hledá v datové množině jistý záznam.
    Lookup Lokalizuje záznam a vrací data obsažená v záznamu.
    MoveBy Přesouvá kurzor o specifikovaný počet záznamů.
    Next Přesouvá kurzor na následující záznam.
    Open Otevírá datovou množinu.
    Post Zapisuje modifikovaná data do databáze nebo je ukládá do vyrovnávací paměti odložených změn.
    Prior Přesouvá kurzor na předcházející záznam.
    Refresh Aktualizuje data v datové množině z databáze.
    RevertRecord Když jsou použity odložené aktualizace, pak tato metoda zruší dříve provedené změny na záznamu, ale nezapíše je do databáze.
    SetFields Nastavuje hodnoty pro všechny položky v záznamu.
    UpdateStatus Vrací současný stav aktualizace při povolené odložené aktualizaci.

    V poslední tabulce jsou uvedeny základní události TDataSet:
     

    Událost Popis
    AfterCancel Generována po zrušení editace záznamu.
    AfterClose Generována po uzavření datové množiny.
    AfterDelete Generována po zrušení záznamu v datové množině.
    AfterEdit Generována po editování záznamu.
    AfterInsert Generována po vložení záznamu.
    AfterOpen Generována po otevření datové množiny.
    AfterPost Generována po odeslání změn do databáze.
    BeforeCancel Generována před zrušením editace záznamu.
    BeforeClose Generována před uzavřením datové množiny.
    BeforeDelete Generována před zrušením záznamu.
    BeforeEdit Generována před uvedením datové množiny do editačního režimu.
    BeforeInsert Generována před vložením záznamu.
    BeforeOpen Generována před otevřením datové množiny (mezi nastavením Active na true a časem skutečného otevření datové množiny).
    BeforePost Generována před odesláním změn do databáze.
    OnCalcFields Generována, když jsou prováděny výpočty počitatelných položek.
    OnDeleteError Generována v případě některých chyb při rušení záznamu.
    OnEditError Generována v případě některých chyb při editaci záznamu.
    OnFilterError Generována při zpřístupňování nového řádku, když Filtered je nastaveno na true.
    OnNewRecord Generována při přidání nového záznamu do datové množiny.
    OnPostError Generována v případě některých chyb při zápisu aktualizace záznamu.
    OnUpdateError Generována v případě některých chyb při zápisu odložených aktualizací do datové množiny.
    OnUpdateRecord Generována, když odložené změny jsou aplikovány na záznam.
  9. Potomci TDataSet (TTable, TQuery a TStoredProc) umožňují používat během návrhu Editor položek. Tento Editor umožňuje vybrat položky, které chceme vložit do datové množiny. K zobrazení Editoru položek zvolíme v místní nabídce komponenty Table, Query nebo StoredProc volbu Fields Editor. Editor položek je nejprve prázdný, což znamená, že do datové množiny jsou uloženy všechny položky. Požadované položky můžeme přidat do datové množiny volbou Add field v místní nabídce. Volbou New field v místní nabídce lze také vytvářet nové položky.

  10. Po přidání položek k datové množině, lze některou položku vybrat a modifikovat její vlastnosti (v Inspektoru objektů). Lze měnit formát zobrazení, omezení a další charakteristiky položky.
  11. Odložená aktualizace umožňuje určit, zda změny jsou prováděny ihned v databázi. Odložená aktualizace je řízena vlastností CachedUpdates. Když odložená aktualizace je povolena, pak provedené změny nejsou zapsány do databáze, ale jsou uloženy ve vyrovnávací paměti na lokálním počítači. Zde jsou uloženy dokud je metodou ApplyUpdates nezapíšeme do databáze. Pro zrušení změn uložených ve vyrovnávací paměti voláme metodu CancelUpdates. Zrušení změn provedených na současném záznamu provedeme voláním RevertRecord.

  12. Pokud odložená aktualizace je zakázána (CachedUpdates je false), pak všechny provedené změny v současném záznamu jsou zapsány do databáze, když kurzor opustí záznam. Je to vhodné řešení pro lokální databáze, ale z mnoha důvodů to není vhodné pro databáze typu klient/server. Použití odložené aktualizace např. snižuje přenos dat po síti.
    Mnoho databází typu klient/server vrací jako výsledek dotazu výsledkovou množinu určenou pouze pro čtení. Jednou z výhod odložené aktualizace je to, že klient může pracovat s lokální kopií datové množiny (určené pouze pro čtení), modifikovat ji podle potřeby a potom zapsat všechny provedené změny do databáze najednou. To je možné, protože databázový server zpracuje aktualizace, vkládání a rušení záznamů z datové množiny určené pouze pro čtení. Lokální databáze má uzamčeny záznamy, když jsou editovány. Pokud je záznam uzamčen, pak ostatní uživatele databáze k tomuto záznamu nemohou přistupovat. Použití odložené aktualizace zkracuje čas uzamčení záznamu.
    Další výhodou odložené aktualizace je to, že uživatel může provést několik změn na datové množině, a potom všechny tyto změny zapsat nebo je všechny zrušit (pokud není možno zapsat všechny změny, pak je vhodné všechny zrušit). Nevýhodou odložené aktualizace je to, že umožňuje několika uživatelům najednou měnit stejný záznam. Tento problém je možno omezit implementací technik v klientské aplikaci, které testují, zda záznam nemodifikoval jiný uživatel.
  13. Komponenta Table (reprezentovaná třídou TTable) poskytuje rychlý a jednoduchý přístup k tabulce. Obvykle používáme komponentu Table při práci s lokálními databázemi a komponentu Query při práci s databázovými SQL servery.

  14. Třída TTable přidává ke svému předkovi TDataSet několik vlastností a metod. Např. metody LockTable a UnlockTable slouží k uzamykání a odemykání tabulky. U těchto metod, je nám již z jejich jména jasné, co dělají. Totéž je možno říci o metodách CreateTable, DeleteTable a RenameTable.
  15. Databázové aplikace často potřebují filtrovat tabulku. Toto je hlavně používáno pro lokální databáze. U databází typu klient/server je výhodnější namísto filtru použít dotaz SQL. Co je to filtr? Předpokládejme, že máme tabulku s mnoha záznamy, ale zajímá nás pouze malá podmnožina této tabulky (pouze několik řádků). Můžeme tedy zadat filtr, který propustí pouze požadované řádky.

  16. Filtry v komponentě Table jsou realizovány dvěma způsoby: prostřednictvím vlastnosti Filter nebo událostí OnFilterRecord. Nejprve si řekneme něco o vlastnosti Filtered. Tato vlastnost určuje, zda tabulka je filtrována. Má-li tato vlastnost hodnotu true, pak na tabulku je aplikován filtr (obsažený ve vlastnosti Filter nebo výsledek obsluhy události OnFilterRecord). Má-li Filtered hodnotu false, pak obsah vlastnosti Filter je ignorován a událost OnFilterRecord není generována. Vlastnost Filter zapisujeme jako jméno položky, operátor a hodnotu. Např.
    FirstName = 'Bob'
    Tento příkaz nám říká: Zobraz všechny záznamy, ve kterých křestní jméno je Bob. Filtry také mohou obsahovat složitější podmínky. Např.
    CustNo = 1384 AND ShipDate < '1.1.94'
    Ve jménech položek a v operátorech není rozlišována velikost písmen, u textových konstant rozlišování velikosti písmen je určeno hodnotou vlastnosti FilterOptions.
    V příkazech filtrů mohou být použity následující operátory (pozor nejedná se o operátory C++):
     
    Operátor Význam
    < menší než
    > větší než
    = rovno
    <> nerovno
    >= větší nebo rovno
    <= menší nebo rovno
    () změna priority jednotlivých operátorů
    [] používá se okolo jmen položek, které obsahují mezery
    AND, OR, NOT logické operátory
  17. Hodnotu vlastnosti Filter lze nastavit v Inspektoru objektů při návrhu nebo přiřazením řetězcové hodnoty za běhu. Ukážeme si to na jednoduché aplikaci. Začneme s vývojem nové aplikace a na formulář umístíme komponenty Table, DataSource a DBGrid. U komponenty Table změníme vlastnost DatabaseName na adresář, do kterého jsme si uložili databázové soubory stažené na začátku této kapitoly, vlastnost TableName změníme na ORDERS.DB a Active na true. U komponenty DataSource nastavíme vlastnost DataSet na Table1. Komponentu DBGrid zvětšíme na celý formulář a změníme její vlastnost DataSource na DataSource1. V mřížce se zobrazí data a můžeme se začít zabývat jejich filtrací. U komponenty Table zadáme jako hodnotu vlastnosti Filter

  18. CustNo = 1384
    a nastavíme vlastnost Filtered na true. Nyní tabulka zobrazuje pouze objednávky pro zákazníka 1384. Můžeme chvíli experimentovat s podmínkou filtru a postupně použít následující hodnoty:
    CustNo = 1510
    CustNo = 1384 and ShipDate < '1.1.94'
    CustNo = 1384 and ShipDate > '1.1.94'
    OrderNo > 1100 and OrderNo < 1125
    Na formulář přidáme ještě tlačítko a obsluhu jeho stisku bude tvořit příkaz:
    Table1->Filter = "CustNo = 1510";
    Takto lze měnit filtr za běhu aplikace. Pokud Filtered je nastaveno na true a vlastnost Filter je prázdná, pak získáme celou datovou množinu.
  19. Jiným způsoben filtrování tabulky je použití události OnFilterRecord. Obsluha této události může obsahovat kód pro filtr tabulky. Nejprve vytvoříme filtr, který nám propustí záznamy s číslem zákazníka 1384 (jako v předchozím příkladu). Tentokrát ale k filtrování použijeme událost OnFilterRecord namísto vlastnosti Filter. U komponenty Table vytvoříme obsluhu událostí OnFilterRecord s následujícím obsahem:

  20. void __fastcall TForm1::Table1FilterRecord(TDataSet *DataSet,
                                               bool &Accept)
    {
      int Hodnota = Table1->FieldByName("CustNo")->Value;
      Accept = (Hodnota == 1384);
    }
    Klíčovým prvkem je zde parametr Accept. Tato událost je generována pro každý řádek v tabulce a pokud parametr Accept je nastaven na true, pak řádek je zobrazen. V našem případě parametr Accept je nastaven na true pro záznamy, ve kterých položka CustNo má hodnotu 1384. Pokud bychom chtěli nahradit další podmínky filtrů, pak můžeme použít v obsluze OnFilterRecord:
    Accept = Table1->FieldByName("CustNo")->Value == 1510;
    nebo
    Accept = Table1->FieldByName("CustNo")->Value == 1510 &&
      Table1->FieldByName("ShipDate")->AsDateTime < TDateTime("1.1.94");
    atd. Používání OnFilterRecord znamená více práce, ale poskytuje větší možnosti než vlastnost Filter.
    Vlastnost FilterOptions určuje, jak filtr bude aplikován. Tato vlastnost je typu množina a může obsahovat prvky foCaseInsensitive a foNoPartialCompare. Implicitně se jedná o prázdnou množinu, tzn. při filtrování se rozlišuje velikost písmen a je povoleno částečné porovnávání. Při povoleném částečném porovnávání je možno ve filtru použít hvězdičku, např.
    LastName = "M*"
    V tomto případě hledáme všechny záznamy u nichž příjmení začíná písmenem M.
  21. Jistý záznam v tabulce lze hledat několika různými metodami. Všechny zde uvedené postupy je možno aplikovat na potomky TDataSet a nejen na TTable. Pro databáze typu klient/server je opět výhodnější používat dotazy SQL. Pro hledání ve filtrované datové množině používáme metody FindFirst, FindNext, FindPrior a FindLast. Tyto metody bezpečně hledají záznamy odpovídající filtru, protože filtr je aplikován vždy při volání těchto metod (jsou nalezeny i modifikované záznamy, které odpovídají podmínce filtru).

  22. Jiný způsob hledání v tabulce využívá metody FindKey a GotoKey. Tyto metody vyžadují index v tabulce. Metoda FindKey hledá položku primárního klíče pro jistou hodnotu. Pokud je použit i sekundární klíč, pak také může být zapojen do hledání. Následující příklad nastavuje sekundární klíč a potom hledá zákazníka číslo 1384:
    Table1->IndexName = "CustNo";
    if (!Table1->FindKey(&TVarRec(1384), 0))
      MessageBox(Handle, "Záznam nenalezen", "Zpráva", MB_OK);
    Třetí způsob hledání v tabulce používá metody Locate a Lookup. Výhodou těchto metod je to, že nevyžadují klíč. Tyto metody se liší. Metoda Locate využívá nejrychlejší dostupnou metodu pro hledání v tabulce (pokud je tabulka indexovaná, pak se index použije). Metoda Lookup provede hledání a vrací hodnoty specifikovaných položek v nalezeném záznamu. Obě metody umožňují specifikovat prohledávanou položku nebo položky a hledanou hodnotu. Následující příklad ukazuje použití metody Locate:
    TLocateOptions Options;
    Options << loPartialKey;
    if (!Table1->Locate("CustNo", "1384", Options))
      MessageBox(Handle, "Záznam nenalezen", "Zpráva", MB_OK);
    Pokud záznam je nalezen, pak Locate vrací true a kurzor je přesunut na nalezený záznam.
  23. Nastavení vzájemného vztahu master/detail komponent Table je snadné. Máme tabulku Customer, která obsahuje informace o našich zákaznících. Tato tabulka má vytvořen index na položce CustNo. Dále máme tabulku Orders, která obsahuje seznam všech objednávek našich zákazníků. Tato tabulka má také položku CustNo, která identifikuje zákazníka. Chceme prohlížet tabulku zákazníků a při výběru některého zákazníka, chceme prohlížet jeho objednávky.

  24. Začneme vývojem nové aplikace a na formulář vložíme komponentu Table a nastavíme u ní tyto vlastnosti: DatabaseName na adresář obsahující naše databázové soubory a TableName na CUSTOMER.DB. Na formulář ještě vložíme komponentu DataSource a nastavíme její vlastnost DataSet na Table1. Na formulář vložíme druhou komponentu Table a druhou komponentu DataSource (vlastnost DataSet nastavíme na Table2). U druhé komponenty Table nastavíme DatabaseName opět na adresář s databázovými soubory, TableName na ORDERS.DB a MasterSource na DataSource1. Dále klikneme na tlačítko se třemi tečkami u vlastnosti MasterFields. Je zobrazeno dialogové okno Návrháře spojení položek. V horní části tohoto okna je kombinovaný ovladač Available Indexes. Zde vybereme CustNo. Nyní mají oba seznamy (Detail Fields i MasterFields) položku CustNo. Vybereme tuto položku v obou seznamech a stiskem tlačítka Add vytvoříme vzájemný vztah tabulek. Stiskem OK okno uzavřeme. Na formulář vložíme dvě komponenty DBGrid, jednu spojíme s DataSource1 a druhou s DataSource2. Nyní již stačí u obou komponent Table změnit vlastnost Active na true. Aplikace je hotova, můžeme ji vyzkoušet. Propojení tabulek je provedeno pomocí společné položky (CustNo).
13. Databázové aplikace I