4. lekce
Přístup k databázi z vyššího programovacího jazyka
Studijní cíl Tento blok popisuje základní principy přístupu k databázi z vyššího programovacího jazyka.
Doba nutná k nastudování
2 - 3 hodiny
Průvodce studiem Při studiu tohoto bloku se předpokládá, že čtenář je obeznámen se základy SQL a běžnými pojmy z oblasti výpočetní techniky a její historie. 1. Úvod K přístupu k databázi je možné využít níže popsaná rozhraní. Výběr závisí na potřebách konkrétní aplikace - požadavcích na výkon, použité technologii, databázové platformě, dostupnosti ovladačů i konkrétní implementaci. Na nejnižší úrovni lze pro komunikaci se systémem pro řízení báze dat (SŘBD) používat jeho nativní rozhraní. Je specifické pro každou databázovou platformu a připojuje se v podobě dynamických knihoven. Využívá se výjimečně v nízkoúrovňových systémech extrémně náročných na rychlost. 2. Rozhraní pro přístup k databázi Efektivnější je využití některého níže popsaného databázového rozhraní. Ta lze v základu rozdělit do dvou linií: a) obecné b) nativní (přímé) Obecná rozhraní jsou nezávislá na použité databázové platformě. Poskytují omezenou množinu služeb. Umožňují relativně jednoduchou změnu databázové platformy i současné využití více typů SŘBD v rámci jedné aplikace. Příkladem mohou být ODBC (JDBC) ovladače.
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
1
Přímá rozhraní jsou závislá na konkrétní databázové platformě (někdy i verzi) a mnohdy také klientské straně (vývojovému nástroji). Výhodou je možnost využití všech dostupných funkcí databázového stroje a jeho výkonu. Příkladem může být OCI (Oracle Call Interface) ovladač. 2.1 ODBC (Open Database Connectivity) Představuje aplikační rozhraní pro přístup k datům v relační databázi nezávisle na databázové platformě (Oracle, Microsoft SQL Server, Microsoft Access, DB2, Sybase, MySQL, PostgreSQL atd.) i operačním systému (Windows, Linux). 2.2 ODBC Driver Manager (Object Linking and Embedding Databases) Správce ovladačů (ODBC DM) tvoří mezivrstvu mezi aplikací a ODBC ovladačem. Zajišťuje načítání potřebných knihoven ODBC ovladače. Umožňuje současnou inicializaci více ovladačů a tedy i jejich přepínání v rámci jedné aplikace. Je tedy možné přistupovat současně k více zdrojům dat. 2.3 OCI (Oracle Call Interface) Rozhraní OCI určené pro platformu Oracle nabízí širokou paletu funkcí pro komunikaci s databázovým serverem a zároveň poskytuje vyšší výkon, než např. ODBC rozhraní. Rozhraní OCI obsahuje (kromě základních funkcí pro práci s db) podporu pro volání PL/SQL, transakce, načítání a ukládání objektu typu LOB/CLOB, funkce pro správu. 3. Připojení k databázi V následujících ukázkách kódu bude pro jednoduchost jako příklad použito jazyka PHP, nicméně volání db. v jiných jazycích (i použitá množina funkcí) je analogické. Pro práci s databází je nejprve nutné navázat spojení a provést autorizaci i autentizaci uživatele. 3.1 Prostřednictvím ODBC Pro vytvoření spojení se používá funkce odbc_connect. Její deklarace vypadá následovně: $database_resource = odbc_connect($dsn, $user, $password);
Parametry: $dsn
– adresa databázového zdroje, např. "localhost"
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
2
$user
– uživatelské jméno (název schématu)
$password
– uživatelské heslo
V případě úspěšného připojení funkce vrací identifikátor spojení, který se dále používá jako parametr pro volání dotazů, pro ukončení spojení, či zjištění vzniklé chyby. 3.2 Prostřednictvím OCI Pro vytvoření spojení prostřednictvím OCI rozhraní oci_connect. Její deklarace vypadá následovně:
lze
využít
metodu
$database_resource = oci_connect($username , $password [, $connection_string [, $character_set]] )
Parametry: $username
– uživatelské jméno (název schématu).
$password
– uživatelské heslo
$connection_string
– adresa databázového zdroje, např. "localhost:1528"
$character_set
- znaková sada, např. "UTF8"
Metoda opět v případě úspěšného spojení vrátí identifikaci spojení. 3.3 Perzistentní spojení Na rozdíl od desktopových aplikací, kde lze udržovat platnost objektu po celou dobu běhu programu, u webových aplikací ztrácí objekt (např. instance databázového spojení) platnost po dokončení požadavku (načtení stránky). Z toho vyplývá, že i v případě dynamických stránek (využívajících AJAX) musí při každém požadavku vznikat nová instance databázového spojení a tedy i nová relace v databázi. Tento problém řeší perzistentní spojení, které v případě opakované žádosti (stejná adresa, uživatelské jméno a heslo) o připojení přidělí již otevřenou volnou instanci. Vše probíhá na pozadí (v režii serveru). Deklarace je obdobná: $database_resource = oci_pconnect($username , $password [, $connection_string [, $character_set]] )
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
3
Respektive (v případě ODBC spojení): $database_resource = odbc_pconnect($dsn, $user, $password);
4. Volání příkazů SQL dotazů Po úspěšném připojení, resp. získání instance spojení lze přikročit k volání samotných příkazů SQL dotazů. 4.1 Syntaxe Syntaxe volaných příkazů SQL dotazů pochopitelně vychází ze specifikace SQL jazyka konkrétní platformy. Jednotlivé příkazy PL/SQL jsou oddělovány středníky. SQL dotazy středníky ukončeny nejsou. 4.2 Vytvoření handleru SQL dotazu Funkce oci_parse vytvoří handler SQL dotazu a vrátí jeho identifikátor. Funkce neprovádí dotaz ani validaci, ta probíhá až při jeho následném spuštění. $statement = oci_parse($database_resource, $query);
4.3 Volání SQL dotazu Funkce oci_execute spustí dotaz. Parametrem je identifikátor $statement získaný funkcí oci_parse. Návratová hodnota funkce je typu bool, a nabývá hodnoty true v případě úspěšného provedení dotazu, false v případě chyby. oci_execute($statement);
4.4 Volání SQL dotazu s parametry Funkce oci_bind_by_name umožňuje bezpečné vázání (binding) parametrů k volanému SQL dotazu. V dotazu je parametr nahrazen zástupným symbolem, který je spárován funkcí oci_bind_by_name s vlastní hodnotou. // Dotaz s použitím zástupných symbolů $query = "UPDATE employees SET emp_name = :name WHERE emp_id = :id"; // Vytvoření handleru dotazu. $statement = oci_parse($database_resource, $query); // Vázání hodnot na zástupné symboly oci_bind_by_name($statement, ":id", 1); oci_bind_by_name($statement, ":emp_name", "Jan");
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
4
// Spuštění dotazu oci_execute($statement);
4.5 Zpracování výstupu dotazu Ke zpracování výstupu dotazu lze použít sadu funkcí (lišících se návratovým typem) typu fetch:
oci_fetch oci_fetch_row oci_fetch_assoc oci_fetch_array oci_fetch_all
Podrobný manuál jednotlivých funkcí je nad rámec tohoto bloku (více viz. PHP manuál dostupný na www.php.net). Nejpoužívanější funkcí je oci_fetch_array, která vrací jednorozměrné pole – řádek na aktuální pozici kurzoru. Přístupové indexy odpovídají názvům sloupců tabulky (dotazu). // Dotaz vracející všechna data z tabulky zaměstnanců $query = "SELECT id, name, phone FROM employees"; // Vytvoření handleru dotazu. $statement = oci_parse($database_resource, $query); // Spuštění dotazu oci_execute($statement); // Průchod kurzorem a vypsání vybraných prvků pole while (($row = oci_fetch_array($statement))){ echo "Jméno: " + $row["name"]; echo "Telefon: " + $row["phone"]; }
5. PL/SQL Volání příkazů PL/SQL jazyka probíhá analogicky jako volání SQL dotazů. Jednotlivé příkazy jsou oddělené středníkem a jsou obsaženy v programovém bloku ohraničeném direktivami begin a end;. Příklad volání PL/SQL: $query = "begin -- Volání db. procedury pridej_osobu s parametry pridej_osobu(:jmeno,:prijmeni);
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
5
end;"; // Vytvoření handleru dotazu. $statement = oci_parse($database_resource, $query); // Vázání hodnot na zástupné symboly oci_bind_by_name($statement, ":jmeno", "Jan"); oci_bind_by_name($statement, ":prijmeni", "Novák"); // Spuštění dotazu oci_execute($statement);
6. Transakce Databázový server prostřednictvím transakcí zajišťuje konzistenci dat v databázových tabulkách a nedělitelnost prováděných změn. Je možné např. ošetřením výjimky vrátit změny provedené v rámci celé transakce. Platnost transakce může být implicitně potvrzena funkcí oci_execute, nebo ji lze potvrdit explicitně voláním funkce oci_commit. 6.1 Volaná implicitně Druhým volitelným parametrem výše uvedené funkce oci_execute je parametr $mode. Defaultně nabývá hodnoty OCI_COMMIT_ON_SUCCESS, tedy v případě úspěšného provedení dotazu je transakce automaticky dokončena. Parametr je možné nastavit na hodnotu OCI_NO_AUTO_COMMIT , tedy nedokončovat transakci po provedení dotazu. // Spuštění dotazu bez potvrzení transakce oci_execute($statement, OCI_NO_AUTO_COMMIT);
6.2 Volaná explicitně Transakce je vytvořena prvním voláním funkce oci_execute s parametrem OCI_NO_AUTO_COMMIT. Transakci lze explicitně potvrdit voláním funkce oci_commit: oci_commit($database_resource);
nebo je možné transakci odvolat voláním funkce oci_rollback: oci_rollback($database_resource);
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
6
7. Výjimky Ošetření výjimek tvoří důležitou součást komunikace s databázovým strojem. V programu lze zachytávat vnitřní (tedy systémem definované) ale i uživatelské výjimky. Syntaktické chyby by měly být rozpoznány a odstraněny již ve fázi testování. Logické chyby (např. typické dělení nulou) nelze s jistotou ve všech případech předvídat, a proto je vhodné jejich ošetření i na více úrovních. V PHP (na rozdíl např. od Javy) nejsou výjimky volání příkazů SQL dotazů zachytávány v try – catch bloku, ale explicitním testováním návratových hodnot (např. funkce oci_execute). Pokud tato funkce vrátí hodnotu false, došlo k výjimce, kterou je třeba ošetřit. Pro zjištění podrobností o vzniklé chybě je určena funkce oci_error, vracející informaci ve tvaru asociativního pole. // Vytvoření handleru dotazu. $statement = oci_parse($database_resource, "SELECT FROM DUAL"); // Volání dotazu oci_execute($statement); // Zachycení výjimky $error = oci_error($statement); // Výpis pole print_r($error); Array ( [code] => 936 [message] => ORA-00936: missing expression [offset] => 7 [sqltext] => SELECT FROM DUAL )
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
7
Pojmy k zapamatování Pojmy: spojení
Open Database Connectivity, Oracle Call Interface, perzistentní
Problém: spojení
bezpečné vázání parametrů dotazu, ošetření výjimek, perzistentní
Shrnutí V této lekci jste seznámili se se základy přístupu a volání příkazů SQL dotazů z jazyka PHP: Perzistentní spojení umožňuje využívat existující relace. Pro vázání proměnných je nutné využívat dostupné funkce ovladače. Klíčovou součástí komunikace je důsledné ošetření výjimek na všech úrovních aplikace. Otázky na procvičení 1. 2. 3. 4.
Jaké jsou výhody nativních rozhraní? Co je perzistentní spojení a kde se využívá? Jakým způsobem jsou zadávány parametry volaných dotazů? Jaké jsou způsoby transakčních zpracování?
Odkazy a další studijní prameny
http://www.oracle.com/technetwork/database/features/oci/index.html http://www.php.net
Odkazy a další studijní prameny
LACKO, L., Oracle – Správa, programování a použití databázového systému. Praha: Computer Press, 2007. ISBN 978-80-251-1490-2. KOSEK, J., PHP – Tvorba interaktivních internetových aplikací. Grada
Publishing, 1999. ISBN 80-7169-373-1 HORTON, I., Java 5. Neocortex, Praha. ISBN 80-86330-12-5.
Jiří Lebduška, David Žák IDAS2/4 – Přístup k databázi z vyššího programovacího jazyka
8