Syntax highlighting of Archiv/Databáze typu klient-server

{{predmet|Databáze typu klient-server|Tomáš Rubač|DBI004}}

= Info =

Celkem poutavá přednáška o SQL z praktického hlediska. 

== Zápočet ==

* triviální SQL program na dvou tabulkách (nemusí být velký, stačí kousek kódu).
* vše ošetřené v databázi: integrita, triggery, procedury k sahání (i s ošetřením výjimek).
* 50-60 řádek.
* postřehy:
** Dost lidem to vracel pro nedostatečné ošetření chyb. Jak jsem vyrozuměl chce ošetřovat i takové chyby jakože někde nastal deadlock.

== Zkouška ==

* jednoduchá písemka (zadání podobné zápočťáku).
* přepsat datový model do SQL i s nějakými triggery/procedurami.
* ústní otázky z teorie
* není potřeba zápočet.

=== Termíny v LS 2004/2005 ===
* [[DBI004 zkouska 2005-05-25 | 25.05.2005 S3 17:30]]
* [[DBI004 zkouska 2005-06-09 | 09.06.2005 S3 17:30]]
* [[DBI004 zkouska 2005-06-23 | 23.06.2005 S3 17:30]]

= Poznámky =
Zatím se jedná o částečný přepis poznámek z [http://urtax.ms.mff.cuni.cz/~novap2am/poznamky/databaze2.sxw] plus doplnění z vlastních poznámek.

--[[User:Maker|Maker]] 21:13, 9 Jun 2005 (CEST)

== DDL - Data definition language ==
{{TODO|Create/Drop *}}

== DML - Data manipulation language ==
{{TODO|Insert, Update, Delete, Select}}

== Zámky ==
{{TODO|Read repeatability/Cursor stability, označování řádků, time marky}}

== Kurzory ==
* kurzor je cosi jako pojmenovaný select
* [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/13_elems14.htm v Oraclu]
* také není standardizované

 create cursor <název> as (select ...) -- vytvoří kurzor
 open cursor <název> -- otevřít (spustit select)
 fetch cursor <název> -- načíst řádek

kam nasávat data:
 into <proměnná>, ... -- někdy je za definicí kurzoru, nejčastěji za open, občas za fetch

cosi jako foreach: spustí select, pak jeden průběh pro každý řádek
 for all <název_kurzoru> -- nebo taky [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/13_elems29.htm#34900]

== Procedury/funkce ==
* Výpočet probíhá přímo v databázi, ušetří se komunikace.
* Funkce se dá používat v selectech, ale nesmí nic měnit – u funkcí se poznamenává, jestli jsou přeložené a jestli něco mění.
* Na některých serverech mohou procedury běžet v samostatných transakcích (vhodné pro logování).
* Není standardizované – každý má svoji implementaci (Oracle: [[wen: PL/SQL| PL/SQL]] [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/toc.htm], [[wen:PostgreSQL|Postgres]]: [[wen:PL/PgSQL|PL/PgSQL]], Microsoft/[[wen:Sybase|Sybase]]: [[wen:Transact-SQL|Transact-SQL]])
* většinou má if, while, přiřazení, volání procedury/funkce, iterace přes kurzor

 create procedure/function <název> ([in/out/on out] <parametr> <typ>, ...) [typ]
 begin
  <my_rec> record type <tabulka> -- proměnná jako jeden řádek tabulky
 exception -- výjimky
 end;

* procedura defaultně běží s právy tvůrce – dá se tím dělat omezení práv, když uživatele k datům přímo nepustím, a nutím ho sahat nepřímo přes procedury
* dají se spouštět dynamické dotazy (je tam funkce, která spustí dotaz textově zadaný v parametru – sqlexecute()? (v Oraclu [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/11_dynam.htm#8074 execute immediate]))
** dotazy se musí pokaždé překládat – jsou pomalejší
** nejsou syntakticky kontrolovány při překladu
** proti běžnému SQL bývá omezeno (obvykle nejde DDL (v Oraclu jde))
** SQL injection

=== Packages ===
* Kód v databázi se spojuje do balíků ([http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/13_elems36.htm packages]) s až téměř objektově definovaným rozhraním
* Package může mít inicializační blok, který se sputí při jeho zavedení do paměti
* Zpřehlednění správy – dají se samostatně verzovat
* Zjednodušení práce s pamětí – natahuje se celý balík najednou
* Když už není potřeba, tak se celý balík z paměti odroluje – někdy jen kód, občas i jeho paměť (to může vést k nepříjemným ztrátám stavu, takže je občas vhodné si je při změně ukládat někam do tabulky)

== Triggery ==
Procedura automaticky spuštěná na základě nějaké události (login a logout uživatele, insert, update a delete nad tabulkou, při systémové chybě).
 [http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_76a.htm <nowiki>create [or replace]</nowiki> trigger] [někdy_jde_pojmenovat]
 on <jméno_tabulky> [before/after/instead of] [insert/update/delete];
* jeden trigger na tabulku teoreticky stačí, ale když se k tomu dostane víc lidí, tak se mezi sebou pobijí. Když je triggerů na jednu věc víc, pořadí jejich spouštění je nedefinované.
* užitečné k ošetřování stavových sloupců a podobných záležitostí (pak je špatné, když trigger nedopatřením odpadne).
* triggery výrazně zpomalují výpočty, dají se dočasně sundat pomocí '''disable trigger''' (když má uživatel právo alter trigger).
* dají se spouštět buď po každém řádku (FOR EACH ROW) nebo jednou za všechny řádky (FOR EACH STATEMENT).
* v insert triggeru vidím nové hodnoty, v delete staré, v update nové i staré. Speciální tabulky new a old (chovají se jako normální tabulky, new se dá upravovat před vložením) (v Oraclu je místo virtuální tabulky defaultně jakýsi record :new, dá se to definovat pomocí klauzule referencing).
* instead of triggery dobré k simulaci vkládání do pohledů, do kterých to normálně nemusí jít.
* update triggery se spouští řádek po řádku.
* v triggeru se nesmí sahat na tabulky, které už triggery ošetřují (takže se nedá udělat cyklické věčné zaplnění).
* v update triggerech se dá používat příkaz if updated (...), který ověřuje, jestli dané sloupce byly změněny.
* triggery mohou pomocí [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/07_errs.htm#943 raise_application_error] házet tajemné a těžko dohledatelné chyby. (A pomocí prostého [http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96624/13_elems38.htm#35710 raise] standardní výjimky.)
* trigger může na některých serverech pomocí příkazu rollback transaction sundat celou operaci, která trigger vyvolala (ne celou transakci jako normální rollback).
* Dají se použít pro udržení konzistence databáze (kromě věcí, na které jsou constrainty). Když vím, že data jsou konzistentní, nemusím se pak zdržovat dodatečnými testy integrity.
* nedají se linkovat z jiných balíků, ale mohou je volat (dobré pro verzování, které s triggery moc nejde) až na příkazy jako rollback transaction výše, které mohou být pouze v triggerech.

== Paralelní/distribuované zpracování ==
* Dva uživatelské profily na jedné databázi.
** Jednoduché, vždy běží obě zároveň, mohou na sebe snadno koukat. Replikuji pomocí triggerů.
** Při upgradu (i bez změny) se ale triggery zneplatní a musí se ručně opravit. Dá se filtrovat přes pohledy. Při změně se musí zastavit obě části.

* Dvě databáze blízko sebe (na lokální síti).
** Triggery selžou při výpadku jednoho stroje. Databáze nebudou konzistentní.
** Řešení: procedury, které budou jednosměrně aktulizovat data.
*** Sypač: Dávám si data do fronty, pak ji procedura jednou za čas přesype na druhou stranu. Fronta je ale citlivá, protože si při updatu můžu pokazit její triggery.
*** Olizovač: Periodicky očumuji druhou databázi, a sosám si nové věci.
*** Olizovač fronty: Jedna strana připravuje frontu, druhá ji nasává.
** Synchronizační proces by měl běžet nezávisle na aplikaci. Změny by se měly v obou aplikacích promítat současně – dvoufázový commit (viz [[Transakce]]).

* Vzdálené databáze.
** Data se musí opravdu posílat sem a tam.
** Typický problém: Pobočka v Praze i v Brně zároveň přidají do číselníku nový výrobek. Po synchronizaci je výrobek v databázi dvakrát (kvůli závislým položkám už nemusí jít ani jeden smazat). Řešení:
*** Administrativní opatření - vkládat do číselníku zboží lze jen v Praze.
*** Předávaní peška - pešek před sebou tlačí všechny updaty a jen ten, kdo má peška, může vkládat do číselníku.

* Spojení ven z databáze a další featury
** Posílací fronty přímo v systému – Oracle Advanced Queing (moc drahé).
** Pipe – nadefinuji trubku, pak do ní posílám data. Na druhé straně z musí data z trubky něco požírat (<pipe> load). Trubka je asynchronní a neřídí se pravidly pro transakce – dobré pro ladící výpisy, ale pro nic jiného.
** Alerter – vystaví majáček, a když se něco stane, tak na něj vypustí alert, který se chová podle transakcí. Procesy koukající na alerty se musí zaregistrovat, a server je pak obešle zprávou. Tím se dá řešit upozornění na stažení updatu při blízkých databázích.
** Job – vlastnost databáze, která plánuje úlohu ke spuštění (jako at/cron).

== Provázání s aplikací ==
[[Image:DBI004 provázání s aplikací.png]]
{{TODO|Rozdělení na vizuální část, aplikační server a databázi; vhodnost bezkontextového spojení do db; pohledy pro lidi vs. exporty, ...}}

= Odkazy =

* Poznámky z přednášky &ndash; [http://urtax.ms.mff.cuni.cz/~novap2am/poznamky/databaze2.sxw sxw] (formát [http://www.openoffice.org OpenOffice.org]), [http://artax.karlin.mff.cuni.cz/~mihao2am/poznamky/databaze.ps ps], [http://artax.karlin.mff.cuni.cz/~mihao2am/poznamky/databaze.pdf pdf]
* [http://otn.oracle.com/pls/db92/db92.homepage Dokumentace Oracle] &ndash; vyžaduje registraci, ale je zcela vyčerpávající. Vedou tam některé linky z textu.