Google+ Followers

pondělí 17. března 2014

Vývoj databázových aplikací III

Komunikace s DB

Od okamžiku, kdy se úspěšně připojíme k databázi, s ní můžeme začít komunikovat. Databázovému stroji předáváme naše požadavky ve formě SQL příkazů a server na ně odpovídajícím způsobem reaguje.
Z pohledu komponent FireDAC je třeba rozlišovat, jaký typ dat DB server na základě zaslaného požadavku vrátí:
• Příkaz nevrací žádná data (DDL, DML, DCL, TCL)
• Příkaz vrací právě jednu hodnotu (Agregační funkce DQL)
• Příkaz vrací výsledkovou sadu neboli "result set" (DQL)

DDL (Data Definition Language) - Příkazy umožňující definovat datové schéma. Mezi základní příkazy DDL patří:
• CREATE (Vytvoří požadovaný typ objektu)
• ALTER (Umožňuje provést změnu struktury existujícího objektu)
• DROP (Odstraní určený objekt z databáze)

DQL (Data Query Language) - Příkazy pro výběr množiny dat z jedné nebo více tabulek nebo pohledů:
• SELECT (Vrací data z dle zadaných kritérií)

DML (Data Manipulation Language) - Obsahuje set příkazů pro práci s uloženými daty. Mezi základní příkazy DML patří:
• INSERT (Vkládá nové záznamy do určené tabulky)
• UPDATE (Provede aktualizaci určených záznamů)
• DELETE (Odstraní příkazem specifikovaná data)

DCL (Data Control Language) - Příkazy pro řízení přístupových práv k jednotlivým objektům databáze. Mezi příkazy DCL patří:
• GRANT (Přiznává uvedená oprávnění určenému uživateli)
• REVOKE (Odebírá uživateli uvedená oprávnění)

TCL (Transaction Control Language) - Příkazy pro řízení transakcí, nebo li sledu operací sdružených do logických bloků. TCL příkazy jsou:
• COMMIT (Provede uložení v rámci transakce provedených změn)
• ROLLBACK (Odvolává transakci a vrací data do původního stavu)

Komunikace se serverem na úrovni připojení

Některé požadavky lze databázovému serveru předat přímo na úrovni připojení. Výhodou je, že odpadá poměrně vysoká režie, kterou vyžaduje obsluha výsledkových sad. Ta je přímo implementovaná v komponentách jako jsou "FDQuery", "FDTable" nebo "FDStoredProc". Pro zaslání příkazu databázi nabízí FireDAC připojení dvě funkce:

ExecSQL - Použití ExecSQL je vhodné pro příkazy, které nevrací žádnou výsledkovou sadu. Případná chybová hlášení můžeme ošetřit za pomoci bloku "try-except". ExecSQL voláme jako metodu objektu ADConnection:


Delphi

procedure TForm1ButtonClick(Sender: TObject);
begin
  try
    FDConnection1.ExecSQL('REVOKE SELECT ON OBJECT::KRAJ TO public');
  except
    on E: EFDDBEngineException do
      ShowMessage(E.ToString);
  end;
end;



C++ Builder

void __fastcall TForm1::ButtonClick(TObject *Sender)
{
  try {
  FDConnection1->ExecSQL("REVOKE SELECT ON OBJECT::KRAJ TO public");
  } catch (EFDDBEngineException &EFDDBEngineException) {
  ShowMessage(UnicodeString(EADDBEngineException.Message));
  }
}

ExecSQLScalar - Potřebujeme-li spustit příkaz, který vrací právě jednu hodnotu (například agregační funkce jako jsou COUNT, SUM, MAX, AVG a podobně), můžeme použít metodu ExecSQLScalar:


Delphi

procedure TForm1ButtonClick(Sender: TObject);
var
  cnt: integer;
begin
  try
    cnt := FDConnection1.ExecSQLScalar('select count(*) from firma');
  except
    on E: EFDDBEngineException do
      ShowMessage(E.ToString);
  end;
  ShowMessage(IntToStr(cnt));
end;


C++ Builder

void __fastcall TForm1::ButtonClick(TObject *Sender)
{
  Integer cnt;
  try {
  cnt = FDConnection1->ExecSQLScalar("select count(*) from firma");
  ShowMessage(IntToStr(cnt));
  } catch (EFDDBEngineException &EFDDBEngineException) {
  ShowMessage(UnicodeString(EFDDBEngineException.Message));
  }
  ShowMessage(IntToStr(cnt));
}

TFDCommand

Další možností pro spouštění příkazů, které nevrací žádnou výsledkovou sadu je použití komponenty TADCommand. Hlavní předností je přímá podpora asynchronního spouštění příkazů, které lze nastavit za pomoci parametru "CmdExecMode".

Parametr "CmdExecMode" může nabývat následujících hodnot:

amBlocking - Vlákno, z kterého bylo volání příkazu spuštěno, je spolu s uživatelským rozhraním blokováno, dokud není akce dokončena.
amNonBlocking - Vlákno, z kterého bylo volání příkazu spuštěno, je blokováno po dobu provádění příkazu. Uživatelské rozhraní blokováno není.
amCancelDialog  - Nastavení je shodné s volbou "amBlocking", navíc je však zobrazen dialog, který umožňuje spuštěnou akci kdykoliv přerušit.
amAsync – Není blokováno ani vlákno z kterého byl příkaz vyvolán, ani uživatelské rozhraní. Volaná metoda okamžitě předává řízení zpět aplikaci.

Pokud v kódu použijeme parametr "CmdExecMode", musí být součástí projektu instance třídy "TFDGUIxAsyncExecuteDialog". Tu můžeme vytvořit v kódu, nebo ji vybrat v paletě komponent a jednoduše ji umístit na formulář. Zobrazený text lze nastavit přes vlastnost "Prompt".

Dialog Asynchronního spuštění



Delphi

procedure TForm1ButtonClick(Sender: TObject);
begin
  FDCommand1.ResourceOptions.CmdExecMode := amNonBlocking;
  FDCommand1.CommandText.add('REVOKE SELECT ON OBJECT::KRAJ TO public');
  try
    FDCommand1.Active := True;
  except
    on E: EFDDBEngineException do
      ShowMessage(E.ToString);
  end;
end;


C++ Builder

void __fastcall TForm1::ButtonClick(TObject *Sender)
{
  FDCommand1->ResourceOptions->CmdExecMode = amNonBlocking;
  FDCommand1->CommandText->Add("REVOKE SELECT ON OBJECT::KRAJ TO public");
  try {
  FDCommand1->Active = True;
  } catch (EFDDBEngineException &EFDDBEngineException) {
  ShowMessage(UnicodeString(EFDDBEngineException.Message));
  }
}

Pokud má být spuštěna uložená procedura, je třeba nastavit vlastnost "ADCommand.CommandKind" na hodnotu "skStoredProc". Pro ostatní příkazy to není nutné, FireDAC rozpozná typ příkazu automaticky.

Spouštění sady SQL příkazů

Jsou situace, kdy je třeba spustit sled více souvisejících SQL příkazů. Většina databázových strojů má k dispozici "oddělovač příkazů", díky kterému lze "dávku" spustit stejným způsobem, jako samostatný příkaz. Tento přístup však má celou řadu omezení. Pro řešení komplexnějších úlohu lze použít databázový "skript".
Rozdíly mezi Dávkou a skriptem:
• Skript může obsahovat i příkazy jiného jazyka než SQL
• Jsou k dispozici informace o průběhu, snazší logování
• Ve skriptu lze použít všechny typy příkazů včetně DDL
• Skript se na rozdíl od dávky může skládat z více transakcí
• Vykonávání skriptu řídí klient, vykonávání dávky server
• Pro spuštění skriptu je třeba mít patřičné rozhraní

Vytvoření a spuštění dávky
Sestavení dávky z jednotlivých řetězců umožňují komponenty "TADCommand" (metoda CommandText.Add()) nebo "TADQuery" (metoda SQL.Add()).


Delphi

procedure TForm1ButtonClick(Sender: TObject);
begin
  FDQuery1.SQL.Add('Use EMBT');
  FDQuery1.SQL.Add('begin tran');
  FDQuery1.SQL.Add('insert into tb values(1,' + QuotedStr('A') + ');');
  FDQuery1.SQL.Add('insert into tb values(2,' + QuotedStr('B') + ');');
  FDQuery1.SQL.Add('insert into tb values(3,' + QuotedStr('C') + ');');
  FDQuery1.SQL.Add('Commit;');
  FDQuery1.Active := True;
end;


C++ Builder

void __fastcall TForm1::ButtonClick(TObject *Sender)
{
  FDQuery1->SQL->Add("Use EMBT");
  FDQuery1->SQL->Add("begin tran");
  FDQuery1->SQL->Add("insert into tb values(1," + QuotedStr("A") + ');");
  FDQuery1->SQL->Add("insert into tb values(2," + QuotedStr("B") + ');");
  FDQuery1->SQL->Add("insert into tb values(3," + QuotedStr("C") + ');");
  FDQuery1->SQL->Add("Commit;");
  FDQuery1->Active = True;
}

Vytvoření a spuštění SQL Skriptu
SQL Skript lze vytvořit v libovolném textovém editoru. Pokud chceme mít k dispozici pomůcky, jako je třeba kontrola a doplňování syntaxe, formátování nebo vizuální vytváření dotazů, je možné využít některý ze specializovaných komerčních nebo open source editorů.
Jak už bylo uvedeno, skripty používají kromě SQL většinou také další "skriptovací" jazyk. Pro jejich spouštění je tak třeba mít k dispozici odpovídající rozhraní (např. SQLPlus pro Oracle, nebo PowerShell pro MSSQL). Součástí FireDAC je utilita "FDExecutor", kterou lze spustit z příkazového řádku.

FireDAC Executor

Možnost spouštět databázové skripty lze zpřístupnit i uživatelům vytvářených aplikací. Podporu práce se skripty zajišťuje FireDAC komponenta "TFDScript". Komponenta umožňuje sestavit skript řádek po řádku, nebo jej jednoduše načíst z určeného souboru a spustit. Na formulář můžeme také přidat "FDGUIxScriptDialog", který informuje uživatele o průběhu zpracování skriptu nebo zobrazí případné chyby.

FireDAC Script Dialog

Skript lze samozřejmě sestavit také v rámci aplikace. Použijeme třídu "TFDScript". Pomocí jejích metod "SQLScripts.Add" můžeme vytvářet jednotlivé skripty. Obsah skriptu se skládá z jednotlivých položek, které přidáváme pomocí metody "SQL.Add".


Delphi

procedure TForm1ButtonClick(Sender: TObject);
begin
  // Přesměrování výstupů do FDGUIxScriptDialog1
  FDScript1.ScriptDialog := FDGUIxScriptDialog1;
  // Odstraní dříve definované SQL skripty
  FDScript1.SQLScripts.Clear;
  // Přidání nového skriptu do seznamu skriptů
  FDScript1.SQLScripts.Add;
  FDScript1.SQLScripts.Items[0].Name := 'Skript1';
  FDScript1.SQLScripts.Items[0].SQL.Add('use embt;');
  FDScript1.SQLScripts.Items[0].SQL.Add('select * from tb1;');
  // Ověření a spuštění vytvořených skriptů
  FDScript1.ValidateAll();
  FDScript1.ExecuteAll();
end;


C++ Builder

void __fastcall TForm1::ButtonClick(TObject *Sender)
{
  FDScript1->ScriptDialog = FDGUIxScriptDialog1;
  FDScript1->SQLScripts->Clear;
  FDScript1->SQLScripts->Add;
  FDScript1->SQLScripts->Items[0]->Name = "Skript1";
  FDScript1->SQLScripts->Items[0]->SQL->Add("use embt;");
  FDScript1->SQLScripts->Items[0]->SQL->Add("select * from tb1;");
  FDScript1->ValidateAll();
  FDScript1->ExecuteAll();
}

View Petr Houf's LinkedIn profileView Petr Houf's profile