Kylix (6) - na data je databáze

21. 5. 2002
Doba čtení: 9 minut

Sdílet

V dnešním dílu se zaměřím na to, jak je v Kylixu realizovaná podpora databází. Budu mluvit jak o lokálních databázích, tak o přístupu na SQL servery. Slibuji, že pokud máte aspoň základní motorické schopnosti, vytvoříme DB aplikaci do 30 minut (data budou uložena v XML).

Bohužel podpora databází není v Open Edition (ale dá se tam doinstalovat – viz minulé díly), ale pouze ve verzi Professional a Enterprise. Rozdíly mezi verzemi uvedu postupně. Můžete si stáhnout trial verzi enterprise na www.borland.com.

Lokální databáze

Jak jsem již v minulých dílech uvedl, BDE (Borland Database Engine) nebylo portováno, takže pokud máte databázi v Paradoxu, DBase, FoxPro, budete muset data přemístit. Při této činnosti (nebo pokud vytváříte novou databázi) je vhodné položit si otázku „Kam s nimi“. Podle mne totiž není vždy nutné používat výkonný SQL server, zvláště pokud bude s databází pracovat jeden uživatel.

Poznámka: detailní informace, jak portovat databázové aplikace na Linux, naleznete v helpu pod heslem „Porting database applications to Linux“.

Kylix umí u lokálních databází pracovat s daty ve formátu XML, nebo v binárním formátu (Borland obojí nazývá MyBase – vidím, že nejen já mám velkou fantazii na jména). Dále je možno ještě využít např. Local Interbase.

V následujícím popisu budu používat tuto terminologii: Databáze – database se skládá z tabulek – table. Každá tabulka se skládá ze sloupců – columns a záznamů – rows. Ty určují pole – field. Rekordset (odpusťte mi ten patvar) znamená množinu záznamů.

Komponenty pro práci s databázemi jsou na paletě komponent v těchto záložkách:

Data Access, DB Controls a dbExpress.

Kylix kromě formulářů – což není nic jiného než vizuální kontejner na komponenty – umí vytvářet i nevizuální kontejnery – datové moduly. Výhodou datového modulu je možnost izolovat nevizuální komponenty na jedno (nebo více) míst a následně se na ně odkazovat z jiných míst.

Třída TDataSet

Základem pro všechny komponenty, které udržují data ve sloupcích a řádcích, je třída TDataSet. Třída udržuje organizovaná data a umožňuje k nim přistupovat. Publikuje několik metod:

  • pohyb v rámci rekordsetu: Open, Close, First, Last, Next, Prior, Locate (hledání)
  • editaci záznamu: Post, Edit, Insert, Append, Delete
  • práci s bookmarky (zapamatování aktuální pozice) a další

Dále několik properties: EOF (jsme na konci rekordsetu), BOF

(jsme na začátku rekordsetu), Fields (jednotlivá pole v rámci aktivního záznamu) a další.

Každý sloupec má jméno. Metoda FieldByName vrátí pole, které je obsaženo v aktuálním záznamu pro sloupec se specifikovaným jménem.

sum:=0;
Query.Open; // otevři dataset
Query.DisableControls; // zakaž aktualizaci DB prvků
try
  Query.First;
  // první záznam (zbytečné, po otevření na něm jsme)
  while not Query.EOF do // nejsme na konci?
  begin
    sum:= sum+Query.FieldByName('Width').AsInteger;
//  sum:= sum+Query.Fields[5].AsInteger;
    //Width je šestým polem (počítáno od nuly)
    Query.Next; //další záznam
  end;
  Query.Close; //zavři dataset
finally
  Query.EnableControls; //povol aktualizaci
end;

Query je instancí následníka TDataSet. Předem upozorňuji, že je to PŘÍKLAD; ano vím, že v SQL je SUM.

Předpokládejme, že Query obsahuje platný SQL příkaz, který vrátí nějaká data. Příklad prochází rekordset a sčítá pole „Width“. Další řádek ukazuje variantu kapánek rychlejší, ale mnohem méně čitelnější (navíc, když změníme SQL příkaz, může se pozice změnit).

Tady bych se ještě zastavil u třídy TField. Je to bázová třída pro všechna databázová pole (TIntegerField, TStringField, TBlobField…). Publikuje virtuální metody (předefinované v následnících) pro přetypování (AsInteger, AsString…). Tedy pokud mám v databázi pole, které je integer (Width), napíšu prostě Query.FieldBy­Name(‚Width‘)­.AsString a mám to jako řetězec. Jednoduché, ne?

Poznámka: FieldByName vrací TField, takže je kompatibilní se všemi jeho následníky.

Query.Edit; //přejdi do editace
Query.FieldByName('width').AsInteger:=10; //změn pole width na 10
Query.Post; //zapiš změny

Příklad editace záznamu.

Malá aplikace

Borland dodává několik demo databází. Já mám nejraději BioLife, protože obsahuje i bloby (textové a grafické). Poznámka: pokud to nevíte, tak BLOB znamená Binary Large OBjects, tj. data, která jsou v databázi uložena v binární podobě (obrázky, zvuky, formátované texty…).

Vytvořte novou aplikaci, dejte Save Project As.. a uložte ji do zvláštního adresáře.

Z palety Data Access vložte na formulář komponentu TDataSource a TClientDataSet. Z palety Standard vložte GroupBox. Z palety Data Controls pod něj vložte TDBGrid a do GroupBoxu TDBMemo,

TDBImage, TDBNavigator. U něj nastavte u vlastnosti VisibleButtons pouze nbFirst, nbPrior, nbNext, nbLast a nbRefresh. Tím jsme zakázali tlačítka pro editaci. U DBImage1 nastavíme vlastnost Stretch na True (obrázek bude přizpůsoben velikosti komponenty).

U vložené komponenty DataSource1 nastavíme vlastnost DataSet na vloženou komponentu ClientDataSet1. Tímto jsme vytvořili datový zdroj pro DB vizuální komponenty. Nyní u všech DB komponent nastavíme vlastnost DataSource na vloženou komponentu DataSource1. Hromadně lze provést vybráním všech komponent myší za držení klávesy CTRL.

Nyní nastavíme „ukotvení“ komponent. Je to důležité hlavně v případě změny rozměrů formuláře uživatelem. Budeme měnit vlastnost Anchors. Pokud máte formulář navržený podle obrázku, tak:

  • DBMemo1 je ukotven vpravo, vlevo, nahoru
  • DBGrid1 je ukotven na všechny strany a navíc má align na bottom

Tímto krokem jsme definovali, že když uživatel bude měnit šířku formuláře, bude se zároveň měnit šířka DBMemo1 a DBGrid1. Ostatní komponenty mají implicitně nastaveno ukotvení vlevo a nahoru.

Databáze je uložena v adresáři „kylix2/demos/db/da­ta“, a to jako cds (binární), nebo xml. Pro naše pokusy si ji překopírujeme do našeho adresáře.

Pravým tlačítkem nad ClientDataSet1 vybereme volbu Load from MyBase table a vybereme příslušný soubor (cds nebo xml). V mřížce by se nám měl objevit seznam. Pokud se tak nestalo, zkontrolujeme, zda máme u ClientDataSet1 nastaveno Active na True a u DataSource1 Enabled na True. Popřípadě zda máme správně propojení (viz výše).

U DBImage1 a DBMemo1 musíme ještě specifikovat pole v rámci datasetu nastavením DataField na „Graphic“ nebo na „Notes“ (nastavení provedeme výběrem ze seznamu sloupců z DB).

V tomto okamžiku je aplikace v podstatě hotová. Pokud vám vadí ta anglické záhlaví v mřížce, můžeme je změnit: pravým tlačítkem nad mřížkou vybereme Columns editor a v něm tlačítko Add all fields. Výběrem jednotlivých polí a změnou Title docílíme požadovaného efektu. Poznámka: zde můžeme změnit i spoustu dalších věcí (pokud tento odstavec vynecháme, berou se hodnoty z DB).

Obrázek aplikace v návrhovém módu (58Kb)

Prosím, všimněte si, že pracujete v návrhovém módu, a přesto vidíte obsah databáze (a nenapsal jsem ani řádek kódu). Pokud uložíme otevřený ClientDataset, bude jeho obsah v souboru .xfm, a tudíž bude přilinkován do výsledného spustitelného souboru. To má někdy výhodu, ale lepší je nahrát data až za běhu. To zajistíme obsluhou dvou událostí formuláře: OnCreate a OnDestroy. V první provedeme načtení dat:

  ClientDataSet1.LoadFromFile('biolife.xml');
  ClientDataSet1.Open;

a ve druhé uvolnění:

  ClientDataSet1.Close;

Nový dataset

Pokud potřebujete vytvořit novou lokální tabulku, vložte na formulář komponentu TClientDataSet a pravým tlačítkem zvolte Fields Editor. V něm pravým tlačítkem New Fields a přidejte si pole podle libosti. Nakonec nad komponentou pravým tlačítkem zvolte Create Dataset a následně Save… Samozřejmě to jde i programově za běhu.

SQL databáze

V předchozím textu jsem popisoval lokální databáze. Vše, co bylo řečeno, použijeme i v následujícím textu, jen k tomu ještě něco přidáme.

Pokud jste dříve pracovali s Delphi pod Windows, měli jste pro přístup k datům na výběr několik možností (MS ADO, BDE, InterBase Express). S příchodem Kylixe vznikla nová technologie (dbExpress), která nyní existuje i pro Delphi 6 a umožňuje sjednotit přístup k těmto databázovým serverům: MySQL, InterBase (Firebird), PostgreSQL (verze Professional), Oracle, DB2, Informix (verze Enterprise). Pokud není váš SQL server přímo podporován, je možné použít ovladače od třetí strany, nebo si je napsat sami (zdrojové kódy jsou dostupné).

Poznámka: verze Enterprise obsahuje vše, co Professional, a věci navíc (o tom příště).

DBExpress tedy obsahuje několik sdílených knihoven převádějících různá rozhraní SQL serverů na jeden tvar, který dokáže dbExpress využívat. V praxi to také může značit, že lze vytvářet program pro jeden SQL server a nakonec ho nasadit proti jinému.

No ale dosti řečí a zkusíme nějakou jednoduchou aplikaci.

Jednoduchá SQL aplikace

Vytvořte novou aplikaci a na formulář vložte komponentu TSQLConnection z palety dbExpress. Já jsem si jako SQL server zvolil MySQL, tudíž u vložené komponenty SQLConnection1 vyberu vlastnost ConnectionName jako MySQLConnection a u vlastnosti Params nastavím potřebné parametry (server, databázi, uživatele …). Tyto parametry se dají nastavit i za běhu. Pokud jste specifikovali přihlašovací jméno a heslo, vypněte LoginPrompt. Jinak poklepáním na komponentu zobrazíte konfigurační dialog, kde si můžete také nastavení uložit. Změnou vlastností Connected na True vyzkoušíte připojení.

Vložte na formulář komponentu TSQLDataSet a nastavte u ní propojení SQLConnection na již existující komponentu. U vlastnosti CommandText nastavte SQL příkaz (můžete použít integrovaný SQL editor) – já jsem vložil „Select id, name From Info“. Vlastností Active můžete opět vyzkoušet, zda je SQL příkaz správný. Tímto jsme vytvořili jednosměrný dataset (daty lze procházet pouze vpřed), který dokáže velmi rychle zprostředkovávat data od serveru.

Poznámka: mimo TSQLDataSet existuje také TSQLQuery,

TSQLTable a TSQLStoredProc. Dále existuje ještě TSQLClientDataSet, který uchovává načtená data v paměti, a ve verzi Enterprise TSQLMonitor, který umožňuje optimalizovat výkon tím, že monitoruje a uchovává informace o komunikaci mezi programem a serverem. Verze Enterprise také obsahuje SQL Builder, což je nástroj na jednoduché vytváření SQL příkazů.

Jenže my chceme zobrazit data v mřížce, kde se dá pohybovat oběma směry, tudíž musíme jednosměrný dataset uchovat v paměti. K tomu slouží TDatasetProvider a náš známý TClientDataset. Propojení není vůbec složité. Dále přidáme ještě TDataSource – protože chceme používat databázové prvky jako DBGrid, který hnedle také vložíme. DBGrid sám o sobě umožňuje uživateli přidávat a editovat záznamy.

Dále na formulář vložíme tři tlačítka s popiskami Open, Close, UpDate a se jmény btnOpen, btnClose, btnUpDate.

Zde jsou uvedeny jejich obsluhy:

procedure TForm1.btnUpDateClick(Sender: TObject);
begin
  ClientDataSet1.ApplyUpdates(-1)
end;

procedure TForm1.btnOpenClick(Sender: TObject);
begin
  ClientDataSet1.Open
end;

procedure TForm1.btnCloseClick(Sender: TObject);
begin
  ClientDataSet1.Close
end;

Jelikož jsou všechny změny provedené uživatelem drženy v ClientDataSetu, je nutno je potvrdit výše uvedeným voláním.

Před spuštěním zkontrolujte, zda je ClientDataSet1­.Active nastaven na False.

Poznámka: ještě pro jistotu uvádím, že všechny databázové komponenty pro získání dat jsou nevizuální, a tudíž nejsou za běhu vidět.

Parametry

Je nepraktické při sebemenší změně vždy vytvářet celý SQL příkaz. Proto v Kylixu existují parametry.

Pokud napíši tento SQL příkaz Select * from Info Where id=:aID, definoval jsem jeden parametr (aID).

if query.Active then //je query otevřen?
  query.Close;
query.SQL.Text:='Select * from Info Where id=:aID';
....
query.ParamByName('aID').AsInteger:=2;
query.Open;

Proměnná Query je typu TSQLQuery a její parametr SQL je typu TStrings. Tato třída, jak jsem již uvedl, spravuje dynamický seznam řetězců a její property Text nám umožní přistupovat k celému seznamu naráz jako k jednomu řetězci.

Tip: pokud potřebujeme pouze provést SQL příkaz jako Update nebo Insert, tak

TSQLConnection pro to publikuje metodu Execute, která provede zadaný příkaz včetně možných parametrů a vrátí rekordset (pokud nějaký je).

Zdrojové kódy obou programů jsou zde.

Transakce

Kylix umožňuje jednoduše používat transakce pomocí volání metod třídy TSQLConnection: StartTransaction, RollBack

a Commit. Lze specifikovat úroveň izolace.

Upozorňuji, že toto je jen ukázka z toho, co Kylix s DB umí, ale pro začátek by to mohlo stačit.

Komponenty – Databázové komponenty

Jelikož je třída TDataSet dostatečně obecná, vznikla spousta komponent pro přístup k různým datovým zdrojům (DBF, textové soubory atd). Doporučuji pohledat na www.torry.net, a to i v sekci pro Delphi, jelikož se většinou jedná o nevizuální komponenty, které se dají jednoduše upravit. Viděl jsem tam i následníka TDataSet, který zapouzdřoval MySQL (bez dbExpress) od nějakého ruského programátora (mimochodem i www.torry.net sídlí v Rusku).

Jinak byla oznámena veřejná beta verze dbExpress driveru pro MySQL 4.0, takže pokud máte MySQL této řady, můžete stahovat.

bitcoin_skoleni

URL: community.bor­land.com/arti­cle/0,1410,28510,00­.html

A co příště?

Příště opustíme zatuchlé prostředí lokálního počítače a vrhneme se do víru Internetu a webovských služeb a povíme si něco o implementaci SOAP a podobných věcí v Kylixu.

Seriál: Kylix