Metadata
Ne vždy je možné programovat komunikaci s databázovým strojem "natvrdo". Důvodem může být, že chceme navrhnout aplikaci tak, aby se byla schopna vypořádat s případnými změnami ve struktuře databáze, nebo chceme poskytnout uživateli možnost sestavovat některé dotazy takzvaně "Ad-Hoc" (tedy v daném okamžiku).
Aby bylo možné sestavit funkční SQL příkaz, musíme mít přístup k "metadatům", které popisují strukturu a vlastnosti jednotlivých objektů databáze. Tyto informace můžeme zjistit hned několika způsoby.
Systémové tabulky
Každý databázový stroj si udržuje informace o objektech, které spravuje. Tyto informace jsou dostupné v závislosti na typu databáze prostřednictvím systémových tabulek, pohledů a procedur. Například seznam existujících tabulek tak lze zjistit spuštěním standardního SQL dotazu:
Oracle:
SELECT owner, table_name FROM dba_tables;
MSSQL:
SELECT * FROM INFORMATION_SCHEMA.TABLES;
Sybase:
SELECT * FROM sys.objects WHERE type = 'U';
InterBase / Firebird:
select rdb$relation_name from rdb$relations
where rdb$view_blr is null and (rdb$system_flag is null or rdb$system_flag = 0);
Na první pohled je zřejmé, že tento přístup má dvě úskalí. Abychom mohli získat informace o existujících objektech (které neznáme), musíme znát strukturu systémových tabulek. A co je horší, řešení založené na systémových tabulkách je "svázáno" s konkrétním databázovým strojem. Z hlediska přenositelnosti tedy nic moc.
Komponenty FireDAC
FireDAC se snaží na rozdíl od systémových tabulek nabídnout obecný koncept, co nejvíce nezávislý na databázové platformě. Protože databázové stroje mohou mít různou architekturu a jednotná není ani terminologie dodavatelů, vychází FireDAC z obecného uspořádání:
Komponenty FireDAC nabízí hned několik způsobů, jak je možné
informace o struktuře databáze získat.
1) Na úrovni připojení
Pokud potřebujeme informace o aktuálním připojení (k jaké databázi je aplikace připojena, pod jakým účtem apod.), stačí zavolat funkci "
GetInfoReport". Ta vrací seznam hodnot, kterou zapíše do určené proměnné typu "
TStrings". Pokud tedy jako parametr této funkce použijeme odkaz na řádky komponenty "
TMemo", dojde k zobrazení všech požadovaných informací.
Příklad 1: načtení informací z "
GetInfoReport"
procedure TForm1.btnGetCnnInfoClick(Sender: TObject);
begin
FDCnn.GetInfoReport(mCnnInfo.Lines);
end;
Pro zjištění informací o jednotlivých objektech pak můžeme využít konkrétní funkce:
GetCatalogNames - pro přehled instancí, katalogů nebo databází, které server spravuje.
GetSchemaNames - pro seznam schemat, jmenných prostorů nebo vlastníků objektů ve vybraném katalogu.
GetTableNames - pro seznam tabulek ve vybraném katalogu a schematu.
GetFieldNames - pro seznam sloupců určené tabulky.
GetKeyFieldNames - pro seznam sloupců obsažených v primárním klíči.
GetIndexNames - pro seznam indexů určené tabulky.
GetPackageNames - pro seznam balíčků ve vybraném katalogu a schematu.
GetStoredProcNames - pro přehled uložených procedur obsažených ve zvoleném balíčku.
GetGeneratorNames - vrací přehled generátorů primárních klíčů.
GetLastAutoGenValue - vrací poslední hodnotu generátoru, sekvence nebo autoikrement určeného sloupce.
Vstupní a výstupní parametry:
Všechny uvedené funkce předávají seznam názvů objektů do určené proměnné typu "TStrings".
TFDPhysObjectScopes
osMy - zahrne do seznamu objekty přihlášeného uživatele
osSystem - zahrne do seznamu systémové objekty
osOther - zahrne do seznamu ostatní objekty
TFDPhysTableKinds
tkSynonym - zahrne do seznamu synonyma
tkTable - zahrne do seznamu tabulky
tkView - zahrne do seznamu tabulkové pohledy
Pattern
Umožňuje specifikovat název objektu za pomoci textového řetězce. Syntaxe je shodná se standardním SQL operátorem "Like", kde '%' nahrazuje libovolný počet znaků a '_' právě jeden libovolný znak.
Příklad 2: Získání přehledu všech tabulek v DB InteBase:
FDCnn.GetTableNames('', '', 'FI%', ListBox.Items, [osMy, osSystem], [tkSynonym, tkTable, tkView], True);
Pozn.: InteBase nevyužívá členění do Katalogů a Schemat. V takovém případě se jako parametr použije prázdný řetězec.
2) Komponenta "FDMetaInfoQuery"
Dalším způsobem, jak za běhu zjišťovat informace o databázových objektech je použití komponenty "FDMetaInfoQuery". Jedná se o standardní "DataSet", jehož obsah lze snadno konfigurovat za pomoci vstupních parametrů.
Typ objektu, jehož metadata potřebujeme získat, určuje parametr "MetaInfoKind". Jeho hodnota může být
mkNone, mkCatalogs, mkSchemas, mkTables, mkTableFields, mkIndexes, mkIndexFields, mkPrimaryKey, mkPrimaryKeyFields, mkForeignKeys, mkForeignKeyFields, mkPackages, mkProcs, mkProcArgs, mkGenerators, mkResultSetFields nebo
mkTableTypeFields.
Příklad 3: Zjištění informací o sloupcích tabulky FIRMA
procedure TForm1.btnFindClick(Sender: TObject);
begin
FDMetaInfoQuery1.Active := False;
FDMetaInfoQuery1.MetaInfoKind := mkTableFields;
FDMetaInfoQuery1.ObjectName := 'FIRMA';
FDMetaInfoQuery1.Wildcard := '';
FDMetaInfoQuery1.Active := True;
end;
3) Objekty "FDTable", "FDQuery" nebo "FDStoredProc"
Pokud známe jméno tabulky nebo uložené procedury, můžeme získat podrobné informace přímo ze získané datové sady.
Příklad 4: Zjištění názvů sloupců z komponenty "
FDQuery"
procedure TfrmMain.ButtonGetFields(Sender: TObject);
var
AList: TStringList;
i: Integer;
begin
AList := TStringList.Create;
FDQuery1.GetFieldNames(AList);
end;
Příklad 5: Zjištění vstupních parametrů uložené procedury:
procedure TfrmMain.ButtonGetSPParams(Sender: TObject);
var
i, n: Integer;
pname: String;
pType: TParamType;
begin
n := FDStoredProc1.ParamCount;
for i := 0 to n - 1 do
begin
pname := FDStoredProc1.Params[i].Name;
pType := FDStoredProc1.Params[i].ParamType;
if pType = TParamType.ptInput then
Memo1.Lines.Add(pname);
end;
end;
Pokud potřebujete navrhnout aplikaci tak, aby se dokázala pružně přizpůsobit případným změnám ve struktuře databáze, nabízí Vám RAD Studio a FireDAC víc než dostatečné možnosti, jak toho dosáhnout.