Objekt Database

Doc. Dr. Vladimír Homola, Ph.D.

Úvod

Ústředním subjektem, ke kterému směřuje výklad databází, je vlastní zdroj dat reprezentovaný objektem Database. Tato kapitola uvádí popis jeho vlastností a metod, stejně jako obecnější informace o datech v relačních databázích.

Použití objektu Database 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.).

Objekt Database je ústředním subjektem zpracování dat, protože jako jediný data skutečně obsahuje - dostupná jeho objekty třídy Recordset. Všechny ostatní objekty databázového prostředí jsou zabezpečovacími, organizačními a pomocnými objekty pří zpracování dat.

Tento článek popisuje pouze základní, nejčastěji používané komponenty objektu Database.

Tabulka relační databáze

Obecné informace

Vyčerpávající popis podstaty relačních databází je možno nalézt zde. V tomto odstavci podstatu jen shrneme bez nároků na exaktnost.

Tabulkou relační databáze se rozumí množina dat uspořádaných do obdélníkového schématu, např.

 

VÝDAJE
Den Cena Nakoupeno
12/7/2002 12.60 Chleba
12/7/2002 8.60 Rohlíky
14/7/2002 15.20 Mléko
... ... ...
15/7/2002 6.40 Jogurt

 

Tabulka relační databáze má v rámci databáze své jméno (table name - zde VÝDAJE). Data jsou organizována do řádků (záznamů, records) a sloupců (columns). V "buňkách" tabulky - v polích záznamů (data fields) - jsou umístěny jednotlivé hodnoty (values) dat.

Typy dat (data type), které je možno do tabulky umístit, jsou dány hostitelskými systémy; všechny systémy zcela určitě podporují typy číselný (numeric), textový (character string, text), datumový (date) a logický (logical, boolean, YesNo). Různé systémy pak podporují různé další typy, které však už nemusí být obecně přenositelné ze systému do systému.

Podstatnou vlastností tabulek relačních databází je toto: typ dat se vztahuje explicitně nikoliv k hodnotě v poli, ale ke sloupci. Typ přiřazený sloupci pak přebírají všechny hodnoty ve sloupci. Jestliže tedy první sloupec tabulky VÝDAJE je typu datumový, pak do libovolného pole prvního sloupce nelze vložit hodnotu jiného typu než datumový (tj. v prvním sloupci jsou samé datumy).

Sloupec tabulky relační databáze je tedy (vedle řádku, záznamu) významnou organizační jednotkou uchování dat. Sloupec tabulky relační databáze má jméno (name), typ (data type) a šířku (column width); šířka je někdy označována jako délka dat (data length) nebo velikost pole (field size) a udává ze vždy v bytech.

Z šířkou sloupce je to následovně. Je-li např. sloupec textový, je to celkem pochopitelné i laikovi: šířka 30 znamená, že textový údaj ve sloupci může mít max. 30 znaků. U jiných typů dat je to však velmi různorodé. Vždy je nutno se informovat v dokumentaci konkrétního systému, jak jsou reprezentována data různých typů.

Realizace jedné tabulky v databázi

Z předchozího textu vyplývá, že tabulka relační databáze se logicky skládá ze dvou navzájem provázaných částí: jednak "záhlaví" tabulky a jednak vlastní data. "Záhlavím" tabulky je dána její struktura: počet sloupců, jejich název, typ atd. Tím je zároveň dán počet a typ datových polí v každém řádku vlastních dat.

Relační databázové systémy v prostředí Windows realizují tabulku relační databáze skutečně jako dva sice oddělené, ale provázané objekty. Objektem definujícím strukturu tabulky je objekt TableDef (definice tabulky). Objektem zpřístupňujícím vlastní data tabulky je objekt Recordset (množina záznamů = řádků). Oba objekty obsahují kromě jiného kolekci objektů typu Field (datové pole). To je zřejmé, protože definice tabulky je především množina definic jednotlivých polí, záznam čili řádek tabulky je především množina dat čili hodnot jednotlivých polí.

Pro použití objektu Database je tedy zapotřebí se seznámit s uvedenými objekty: Field, TableDef a Recordset. Vztah mezi nimi se snaží ukázat následující obrázek:

 

Realizace tabulek v databázi

Předchozí odstavec ukázal realizaci jedné tabulky. Objekt Database v pojetí Microsoft Jet však může tabulek obsahovat více. Z hlediska tabulek relační databáze je možno podat zjednodušené schéma databáze - zde např. nějaká hypotetická databáze pro domácí účetnictví:

 

 

Upozorňujeme, že na tomto schématu jsou znázorněny pouze objekty týkající se tabulek! Databáze obsahuje ještě řadu dalších objektů, zvláště kolekci QueryDefs obsahující příkazy jazyka SQL.

Kolekce objektu Database

TableDefs

TableDefs je kolekce obsahující všechny objekty třídy TableDef dané databáze (viz také níže metoda CreateTableDef). Využívá se pouze v pracovních prostorech Microsoft Jet. Protože objekt TableDef je podstatným objektem obsahujícím informace o struktuře tabulky dat, je popsán v samostatné kapitole zde.

Jednotlivé prvky kolekce TableDefs jsou dostupné voláním (implicitní) metody Item kolekce; je-li db identifikátorem otevřené databáze a např. VÝDAJE jméno její tabulky, pak příslušný objekt TableDef z kolekce TableDefs je přístupný zápisem

db.TableDefs("VYDAJE")

nebo

db.TableDefs![VYDAJE]

nebo (při znalosti ordinálního čísla i tabulky v kolekci)

db.TableDefs(i)

Recordsets

Recordsets je kolekce obsahující všechny otevřené objekty třídy Resordset dané databáze (viz také níže metoda OpenRecordset). Protože objekt Recordset je podstatným objektem zpřístupňujícím vlastní data, je popsán v samostatné kapitole zde.

Objekt Recordset kolekce Recordsets reprezentuje jednu otevřenou tabulku. Jakmile se otevře objekt třídy Recordset (voláním metody OpenRecordset objektu Database), automaticky se přidá do kolekce Recordsets. Jakmile se otevřený objekt třídy Recordset zavře (voláním své metody Close), z kolekce Recordsets se odstraní.

Kolekce Recordsets může obsahovat více různých objektů třídy Recordset odkazujících na stejný zdroj dat.

Jednotlivé prvky kolekce Recordsets jsou dostupné voláním (implicitní) metody Item kolekce; je-li db identifikátorem otevřené databáze a např. VÝDAJE jméno její tabulky, pak příslušný objekt Recordset z kolekce Recordsets je přístupný zápisem

db.Recordsets("VYDAJE")

nebo

db.Recordsets![VYDAJE]

nebo (při znalosti ordinálního čísla i množiny dat v kolekci)

db.Recordsets(i)

QueryDefs

QueryDefs je kolekce obsahující všechny objekty třídy QueryDef (viz také níže metoda CreateQueryDef). Objekt QueryDef representuje jeden dotaz (query) realizovaný dotazovacím jazykem SQL.

Jednotlivé prvky kolekce QueryDefs jsou dostupné voláním (implicitní) metody Item kolekce; je-li db identifikátorem otevřené databáze a např. CELKEM jméno jejího dotazu, pak příslušný objekt QueryDef z kolekce QueryDefs je přístupný zápisem

db.QueryDefs("CELKEM")

nebo

db.QueryDefs![CELKEM]

nebo (při znalosti ordinálního čísla i dotazu v kolekci)

db.QueryDefs(i)

Relations

Relations je kolekce obsahující všechny vytvořené vazby - relace, objekty třídy Relation (viz také níže metoda CreateRelation). Jeden objekt Relation representuje jednu vazbu mezi dvěmi tabulkami a udržuje informace o vlastnostech této vazby.

Pro vytvoření a uplatnění vazby (objektu Relation) je zapotřebí nejprve vytvořit nový objekt třídy Relation metodou CretaeRelation objektu Database. Po přiřazení hodnot do vlastností tohoto nového objektu je možno objekt přidat do kolekce Relations její metodou Append. Uložení definované vazby se však provede až při uzavření databáze a její uplatnění až při novém otevření databáze. Zrušení vazby provede metoda Delete kolekce Relations.

Jednotlivé prvky kolekce Relations jsou dostupné voláním (implicitní) metody Item kolekce; je-li db identifikátorem otevřené databáze a např. VýdajeObchody jméno její vazby, pak příslušný objekt Relation z kolekce Relations je přístupný zápisem

db.Relations("VýdajeObchody")

nebo

db.Relations![VýdajeObchody]

nebo (při znalosti ordinálního čísla i relace v kolekci)

db.Relations(i)

Properties

Každý objekt DAO (s výjimkou objektů Error a Connection) obsahuje kolekci Properties (Vlastnosti - viz také níže metoda CreateProperty). Do ní jsou zařazeny především jisté "vestavěné" vlastnosti - objekty třídy Property. Tyto objekty, často nazývané prostě jen "Vlastnosti", jednoznačně charakterizují danou instanci daného objektu, její chování, poskytovaná data apod.

Do kolekce Properties však mohou aplikace vkládat další objekty třídy Property; užívá se pak označení "Uživatelské vlastnosti" nebo "Vlastnosti definované uživatelem". Tyto uživatelské vlastnosti jsou uloženy pouze v dané konkrétní instanci objektu (např. v konkrétní databázi - souboru MDB), nikoliv v obecném prototypu objektu dané třídy. Vloží-li se tedy do kolekce vlastností konkrétní databáze vlastnost např. MAJITEL, nově vytvářené databáze žádnou vlastnost MAJITEL mít nebudou.

Uživatelských vlastností hojně využívá program Access. Do kolekce Properties např. objektu Field vkládá vlastnosti využívané pak Accessem pro formátování, specifické kontroly aj.

Přidání uživatelské vlastnosti se provede ve dvou krocích. Nejprve se vytvoří nová instance objektu Property voláním metody CreateProperty objektu Database, pak se tato instance přidá do kolekce voláním metody Append kolekce Properties. Protože prvky kolekce jsou zařazovány s klíčem rovným jménu vlastnosti, nelze přidat vlastnost se jménem, které už v kolekci existuje.

Uživatelskou vlastnost lze z kolekce vyjmout, vestavěnou vlastnost nikoliv.

Jednotlivé prvky kolekce Properties jsou dostupné voláním (implicitní) metody Item kolekce; je-li obj identifikátorem konkrétní instance nějakého objektu (např. databáze, pole apod.) a např. MAJITEL jméno její vlastnosti, pak příslušný objekt Property z kolekce Properties je přístupný zápisem

obj.Properties("MAJITEL")

nebo

obj.Properties![MAJITEL]

nebo (při znalosti ordinálního čísla i vlastnosti v kolekci)

obj.Properties(i)

Vestavěné vlastnosti zpřístupňuje také zápis (příklad pro vlastnost Name)

obj.Name

který se nedá použít pro vlastnosti definované uživatelem.

Containers

Containers je kolekce obsahující všechny objekty třídy Container dané databáze. Využívá se pouze v pracovních prostorech Microsoft Jet. Kolekce obsahuje "vestavěné" kontejnery definované databázovým strojem Microsoft (Databases obsahující uložené databáze, Tables obsahující uložené tabulky a dotazy, Relations obsahující uložené vazby). Uživatelské aplikace mohou definovat své vlastní kontejnery a vkládat je do kolekce kontejnerů. Aplikace Access např. definuje kontejnery Modules, Reports, Macros.

V jednoduchých databázových aplikacích se nevyužijí, tento článek je proto dále nepopisuje.

Metody objektu Database

CreateTableDef

Metoda je funkcí, která předá nově vytvořenou instanci objektu třídy TableDef (definice tabulky relační databáze). Lze použít jen v pracovních prostorech Microsoft Jet. Protože objekt TableDef je evidentně jedním z nejdůležitějších při zpracování databází, je podrobně samostatně popsán zde.

Syntaxe volání metody je následující:

 db.CreateTableDef (name, atr, src, con)

Značí přitom:

Metoda sama sice novou instanci objektu třídy TableDef vytvoří, ale sama ji do kolekce TableDefs nepřidá. Důvod je ten, že objekt TableDef obsahuje řadu vlastností, které aplikace potřebují před přidáním do kolekce nastavit (především její datová pole - fields; to je před zařazením do kolekce zapotřebí definovat alespoň jedno). Pozdější zařazení do kolekce provede metoda Append kolekce. Po zařazení do kolekce lze dále některé vlastnosti měnit, ale některé ne.

Pokud se při volání metody CreateTableDef nezadají některé parametry, lze příslušným vlastnostem přiřadit hodnotu právě po vytvoření objektu TableDef ale před jeho přidáním do kolekce.

Příklad, který v databázi DOMACNOST vytvoří novou tabulku OBCHODY:

Dim db As Database, td As TableDef
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
Set td = db.CreateTableDef("OBCHODY")
...
db.TableDefs.Append td
db.Close

CreateQueryDef

Metoda je funkcí, která předá nově vytvořenou instanci objektu třídy QueryDef (definice dotazu - příkazu v SQL).

Syntaxe volání metody je následující:

 db.CreateQueryDef (name, sql)

Značí přitom:

Metoda vytvoří novou instanci objektu třídy QueryDef. Jestli ji automaticky do kolekce QueryDefs přidá nebo nepřidá, se rozhodne takto:

Není-li zadán parametr name, je nutno nejpozději před zařazením do kolekce QueryDefs obsadit vlastnost Name v kolekci jedinečným jménem. Provedení příkazu SQL však lze zajistit i bez zařazení objekty QueryDef do kolekce.

Není-li zadán parametr sql, je nutno nejpozději před provedením dotazu obsadit vlastnost SQL nově vytvořeného objektu QueryDef. V Microsoft Jet je textem SQL jeden příkaz SQL. V ODBCDirect je textem SQL specifikován příkaz SQL nebo procedura a její parametry ve formátu užívaného Microsoft SQL Serverem.

Zařazení do kolekce provede metoda Append kolekce. Provedení dotazu zajistí metoda objektu Database Execute (tzv. "akční" dotazy) nebo OpenRecordset (příkaz Select).

Pro odstranění objektu QueryDef z kolekce QueryDefs se použije metoda Delete kolekce. V ODBCDirect se objekt QueryDef "zavírá" svou metodou Close.

Příklad, který v databázi DOMACNOST vytvoří (ale neprovede - viz metoda Execute) nový "akční" dotaz (= příkaz SQL) se jménem PřidejSídlo pro přidání sloupce SIDLO do tabulky OBCHODY:

Dim db As Database, sq As String
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
sq = "Alter Table OBCHODY Add Column SIDLO Text(20)"
db.CreateQueryDef "PřidejSídlo", sq
...
db.Close

V příkladu nebylo nutno explicitně definovat objekt třídy QueryDef, protože při volání metody CreateQueryDef bylo použito neprázdné jméno dotazu a tedy nově vytvořený dotaz byl rovnou zařazen do kolekce QueryDefs.

CreateRelation

Metoda je funkcí, která předá nově vytvořenou instanci objektu třídy Relation (relace, vazba z jedné tabulky do druhé).

Syntaxe volání metody je následující:

 db.CreateRelation (name, tbl, fgn, atr)

Značí přitom:

Metoda sama sice novou instanci objektu třídy Relation vytvoří, ale sama ji do kolekce Relations nepřidá. Důvod je ten, že objekt Relation obsahuje řadu vlastností, které aplikace potřebují před přidáním do kolekce nastavit (především její datová pole - fields; to je před zařazením do kolekce zapotřebí definovat alespoň jedno na obou stranách vazby). Pozdější zařazení do kolekce provede metoda Append kolekce. Po zařazení do kolekce nelze dále žádné vlastnosti relace měnit.

Před přidáním musí v databázi existovat obě tabulky (tbl i fgn), příslušná vazební pole a při požadavcích na referenční integritu příslušné indexy.

Následující tabulka popisuje nejdůležitější konstanty použitelné ve výrazu atr - je-li jich více, sčítají se (dbRelationUpdateCascade + dbRelationDeleteCascade):

 

Konstanta Význam
dbRelationUnique Typ vazby je 1:1
dbRelationDontEnforce Pro vazbu se nepožaduje zajištění referenční integrity
dbRelationUpdateCascade Požaduje se aktualizace v kaskádě
dbRelationDeleteCascade Požaduje se vypuštění v kaskádě

 

Problematika vazeb v relačních databázových systémech je obecně složitější, proto v tomto článku zaměřeném na úvodní informace pro jednoduché aplikace není dále popsána.

CreateProperty

Metoda je funkcí, která odevzdá nově vytvořený objekt třídy Property (vlastnost, v tomto případě definovaná uživatelem, nikoliv jako vlastnost objektu třídy Database!) s danými vlastnostmi: jméno (name), typ (type), hodnota (value) případně indikace, zda vlastností je DDL objekt (data definition language).

Syntaxe je následující:

db.CreateProperty (name, type, value, DDL)

kde značí:

Metoda se používá pro vytvoření nového objektu třídy Property, který se např. posléze přidá do kolekce Properties objektu Database. Všechny parametry jsou nepovinné. Pokud se neuvedou parametry metody CreateProperty, je nutno vlastnosti adekvátně nastavit před přidáním do kolekce.

Pro zařazení vlastnosti do kolekce se použije metoda Append kolekce Properties, pro vypuštění její metoda Delete.

OpenRecordset

Snad nejdůležitější metoda objektu Database. Vytvoří nový objekt třídy Recordset (množina záznamů, řádků) a přidá ho do kolekce Recordsets (popsáno zde); tím zpřístupní data pro jejich zpracování.

Vlastní množina záznamů může mít nejroztodivnější původ a může být otevírána s ohledem na miliony aspektů systémového i databázového prostředí. Tento článek se omezuje výhradně na jednoduché aplikace v prostředí Microsoft Jet, proto neuvádí obsáhlý popis všech možností. Uvažuje jen data nuď přímo v tabulce dat, nebo vzniklá příkazem Select z SQL.

Syntaxe je následující:

db.OpenRecordset (zdr, typ, opt, lck)

pro zpřístupnění dat tabulky, a

qd.OpenRecordset (typ, opt, lck)

pro zpřístupnění dat provedením příkazu Select v SQL uloženého jako dotaz. Značí přitom:

Execute

Metoda provede "akční" dotaz (tj. příkaz SQL připravený v objektu třídy QueryDef) nebo vykoná přímo zadaný příkaz SQL. Týká se příkazů SQL kromě příkazu Select.

Syntaxe je následující:

db.Execute src, opt

pro přímé vykonání příkazu SQL, nebo

qr.Execute opt

kde značí:

"Akční" dotaz (tj. každý příkaz SQL kromě Select) nějakým způsobem mění data. Protože obecně ke zdroji dat může mít přístup více uživatelů a protože při vykonávání příkazu může dojít k chybě, musí mít aplikace alespoň minimální možnost definovat chování v případě výskytu nějaké kolizní situace. To umožňuje volitelný parametr Opt metody Execute, tvořený jednou nebo součtem některých z níže uvedených konstant (všechny se týkají jen pracovních prostorů Microsoft Jet):

 

Konstanta Význam
dbDenyWrite Zakazuje zápis jiným uživatelům
dbInconsistent Implicitní: vykoná inconsistent změny
dbConsistent Vykoná consistent změny
dbFailOnError Vrátí zpět provedené změny při výskytu chyby
dbSeeChanges Generuje chybu, jestliže jiný uživatel změní data

 

Parametry dbInconsistent a dbConsistent se navzájem vylučují. Nekonzistentní (inconsistent) změna je přitom taková, která dovolí přístup ke všem datovým polím objektu Recordset vzniklým z více zdrojů (např. vazbou 1:N dvou tabulek). Lze např. změnit hodnotu vazebního pole na straně "N" tabulky (pak nebude odpovídat vazebnímu poli na straně "1" tabulky), ledaže by to zakázala referenční integrita. Konzistentní změny (consistent) to nedovolují: nelze změnit vazební pole na straně "N" tabulky na hodnotu, která není na straně "1" tabulky.

Protože "akční" dotaz nevrací žádná data, ani metoda Execute nevrací žádný objekt třídy Recordset. Jestliže však metoda provedla nějaké změny v datech (přidala nebo vypustila řádky nebo změnila jejich obsah), je počet takových řádků po vykonání dostupný ve vlastnosti RecordsAffected objektu Database nebo QueryDef.

Příklad, který v databázi DOMACNOST provede (ale neuloží jako dotaz) "akční" příkaz SQL, kterým se přidá sloupec SIDLO do tabulky OBCHODY:

Dim db As Database, sq As String
Set db = DBEngine.OpenDatabase("C:\KURS\DOMACNOST.MDB")
sq = "Alter Table OBCHODY Add Column SIDLO Text(20)"
db.Execute sq
...
db.Close

Close

Metoda zavře otevřenou databázi. Syntaxe je

db.Close

kde db je identifikátor otevřené databáze. Pokus o zavření již zavřené databáze způsobí chybu. Otevřená databáze se zavře s tím, že pokud probíhají neukončené změny (metodou Edit, transakcí) nebo je otevřen nějaký Recordset, změny se neprovedou, transakce se vrací do původního stavu, Recordset se zavře.

Alternativou k volání metody Close je obvyklé uvolnění objektu z paměti:

set db = Nothing

Vlastnosti objektu Database

CollatingOrder

Vrací hodnotu typu Long specifikující pořadí řazení (obecně způsob porovnávání textových řetězců) z hlediska národního. Hodnotu je nejlépe testovat na konstanty dbSortCzech (čeština), dbSortGeneral (angličtina, francouzština, němčina, portugalština, italština a moderní španělština).

Vlastnost CollatingOrder databáze platí pro všechny nově vytvářené tabulky databáze, pokud se v těchto tabulkách neřekne jinak.

QueryTimeout

Lze použít jen u datových zdrojů ODBC. Nastavuje nebo vrací počet vteřin čekání, než nastane chyba způsobená např. obsazením dat jiným uživatelem.

Vlastnost QueryTimeout databáze platí pro všechny nově vytvářené dotazy databáze, pokud se v těchto dotazech neřekne jejich vlastností ODBCTimeout jinak.

RecordsAffected

Vrací hodnotu typu Long ve významu počtu řádků, které byly změněny naposledy volanou metodou Execute databáze (viz shora).

 

 

Orig. 4 / 1999

Rev. 07 / 2002