Pohledy (views) v MySQL
- 15. Duben 2009
- Publikováno v MySQL
- Napište komentář
Databázové pohledy by se daly popsat jako uložené definice výběrových dotazů. Pro jednoduchost si lze pohled představit jako tabulku, se kterou lze za jistých okolností i stejně pracovat. Pohled může vycházet z jedné či více tabulek a může obsahovat i odvozené atributy, které se přímo ve zdrojových tabulkách nevyskytují.
Proč je používat
Hlavní důvod pro použití pohledů by mělo být zjednodušení práce s databází. Často vypisujete záznamy z přirozeného spojení více tabulek? Pokud ano, je právě zde vhodné místo pro použití pohledu. Výběr konkrétních záznamů pak budete provádět na vytvořeném pohledu.
Neméně podstatný důvod pro použití pohledu je bezpečnost, kterou přináší omezení dostupné množiny dat. Máte-li tabulku s několika desítkami atributů a různí uživatelé pracují jen se zlomkem jejich počtu, je vhodné dát jim k dispozici jen atributy, které používají a zbytek pomocí pohledu "odfiltrovat".
Použití pohledů se pokusím vysvětlit na několika příkladech.
Příprava databáze
V databázi vytvoříme dvě tabulky
CREATE TABLE `test_view`.`objednavka` (
`id_objednavka` INT( 4 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_zbozi` INT( 4 ) NOT NULL,
`kusu` INT( 4 ) NOT NULL
);
CREATE TABLE `test_view`.`zbozi` (
`id_zbozi` INT( 4 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`popis` VARCHAR( 10 ) NOT NULL,
`cena` INT( 4 ) NOT NULL
);
a následně je naplníme daty
VALUES ('rohlik', '2'),
('maslo', '19'), ('salam', '24'),
('pomeranc', '8'), ('testoviny', '37');
INSERT INTO `objednavka` (`id_zbozi`, `kusu`)
VALUES ('2', '5'), ('4', '2'),
('1', '7'), ('2', '18'), ('3', '5');
Syntaxe vytvoření pohledu
Pro naše účely si vystačíme se zjednodušenou syntaxí
[(seznam_atributu)]
AS dotaz_vybirajici_data;
kde seznam_atributu je výčet jmen atributů výsledného pohledu. Nejde o jejich výběr. Je tedy nutné aby jejich počet byl stejný jako počet atributů, který vrátí dotaz_vybirajici_data. Použití této volitelné části má smysl pokud chceme pro pohled zvolit jiná jména atributů. Je třeba mít však na mysli, že s těmito atributy budeme chtít dále pracovat, proto nepoužívejte žádné dlouhé a složité názvy.
Kdo by chtěl pohledy zkoumat detailněji, může nahlédnout do dokumentace.
Pokud vytváříme pohled jako výběr všech sloupců tabulky pomocí * (hvězdičky), je to bráno, jako bychom uvedli výpis všech sloupců. Pokud později zdrojovou tabulku modifikujeme, změny se do pohledů neprojeví.
-> AS
-> SELECT * FROM objednavka;
Query OK, 0 rows affected (0.00 sec)
mysql> ALTER TABLE objednavka
-> ADD zaplaceno BOOL NOT NULL;
Query OK, 5 rows affected (0.05 sec)
Records: 5 Duplicates: 0 WARNINGS: 0
mysql> SELECT * FROM v_pokus;
+---------------+----------+------+
| id_objednavka | id_zbozi | kusu |
+---------------+----------+------+
| 1 | 2 | 5 |
| 2 | 4 | 2 |
| 3 | 1 | 7 |
| 4 | 2 | 18 |
| 5 | 3 | 5 |
+---------------+----------+------+
5 rows in SET (0.00 sec)
Smazání pohledu je jako vždy jednoduché
Query OK, 0 rows affected (0.00 sec)
Příklady
Vytvoříme si pohled se seznamem objednávek, kde místo id_zbozi bude jeho název. Následně pak nad pohledem použijeme dotaz s omezením na počet kusů.
-> AS
-> SELECT o.id_objednavka, z.popis,
-> o.kusu, o.zaplaceno
-> FROM objednavka o, zbozi z
-> WHERE o.id_zbozi = z.id_zbozi;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM v_objednavky
-> WHERE kusu> 5;
+---------------+--------+------+-----------+
| id_objednavka | popis | kusu | zaplaceno |
+---------------+--------+------+-----------+
| 3 | rohlik | 7 | 0 |
| 4 | maslo | 18 | 0 |
+---------------+--------+------+-----------+
2 rows in SET (0.00 sec)
Možná budeme často vypisovat i celkovou cenu za objednávku, pak se nám bude hodit pohled obsahující nový sloupec, odvozený z jednotkové ceny a počtu kusů.
-> (id_objednavka, zbozi, kusu, cena, zaplaceno)
-> AS
-> SELECT o.id_objednavka, z.popis,
-> o.kusu, o.kusu*z.cena, o.zaplaceno
-> FROM objednavka o, zbozi z
-> WHERE o.id_zbozi = z.id_zbozi;
Query OK, 0 rows affected (0.07 sec)
mysql> SELECT * FROM v_objednavky2
-> WHERE cena> 50;
+---------------+-------+------+------+-----------+
| id_objednavka | zbozi | kusu | cena | zaplaceno |
+---------------+-------+------+------+-----------+
| 1 | maslo | 5 | 95 | 0 |
| 4 | maslo | 18 | 342 | 0 |
| 5 | salam | 5 | 120 | 0 |
+---------------+-------+------+------+-----------+
3 rows in SET (0.00 sec)
Lze také vytvořit pohled z pohledu, či ze spojení pohledu a další tabulky.
-> AS
-> SELECT * FROM v_objednavky2
-> WHERE cena> 100;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM v_objednavky3;
+---------------+-------+------+------+-----------+
| id_objednavka | zbozi | kusu | cena | zaplaceno |
+---------------+-------+------+------+-----------+
| 4 | maslo | 18 | 342 | 0 |
| 5 | salam | 5 | 120 | 0 |
+---------------+-------+------+------+-----------+
2 rows in SET (0.00 sec)
Aktualizovatelné pohledy
Za jistých okolností lze nad pohledy volat i příkazy INSERT, UPDATE a DELETE. Tyto aktualizovatelné (updatable) pohledy však nesmí obsahovat:
- agregované funkce (min, max, sum, avg, count, ..)
- klauzuli DISTINCT pro výpis jedinečných záznamů
- klauzuli UNION pro slučování výsledků dotazů
- GROUP BY pro seskupování hodnot
- poddotaz v podmínce WHERE, který se odkazuje na tabulku uvedenou za klíčovým slovem FROM našeho pohledu
Neuvedl jsem zde všechny možnosti, jen ty, se kterými se můžete běžně setkat. Zájemci o detaily opět nahlédnou do dokumentace.
Obecně lze říct, že v aktualizovatelném pohledu musí každý záznam odpovídat právě jednomu záznamu zdrojových dat.
Příklad aktualizace dat pomocí pohledu.
-> WHERE popis = 'pomeranc';
+---------------+----------+------+-----------+
| id_objednavka | popis | kusu | zaplaceno |
+---------------+----------+------+-----------+
| 2 | pomeranc | 2 | 0 |
+---------------+----------+------+-----------+
1 row in SET (0.01 sec)
mysql> UPDATE v_objednavky
-> SET kusu = kusu+2
-> WHERE popis = 'pomeranc';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 WARNINGS: 0
mysql> SELECT * FROM objednavka
-> WHERE id_objednavka = 2;
+---------------+----------+------+-----------+
| id_objednavka | id_zbozi | kusu | zaplaceno |
+---------------+----------+------+-----------+
| 2 | 4 | 4 | 0 |
+---------------+----------+------+-----------+
1 row in SET (0.00 sec)
Pokud bychom však chtěli pomocí pohledu smazat některý záznam (případně vložit nový), příkaz skončí chybou. To kvůli tomu, že záznamy v uvedených pohledech jsou složeny z dat dvou tabulek spojených atributem id_zbozi.
Opravdu vyborne clanecky k zakladnimu pochopeni problematiky. Ode me velky dik autorovi.
Super!