MySQL a odstraňování záznamů. Ale - je vůbec dobrý nápad něco v databázi mazat? Nedalo by se to obejít? Přečtěte si!
26.4.2005 15:00 | Petr Zajíc | přečteno 55071×
Protože jsme se v předchozích dvou dílech věnovali příkazům, pomocí nichž lze data do MySQL vkládat a upravovat, asi nikoho nepřekvapí, že dnes se budeme věnovat mazání záznamů.
MySQL má pro odstranění záznamů z tabulky příkaz DELETE. Ten odstraní nula nebo více řádků. Jeho nejjednodušší forma je:
delete from [názav
tabulky];
Příkaz uvedený výše odstraní z tabulky všechny záznamy. Pozor, v některých DBMS je přípustná i forma příkazu s hvězdičkou:
delete * from [názav
tabulky];
kterou však MySQL nevezme, a příkaz takto napsaný by skončil chybou. Samozřejmě, málokdy budete chtít odstranit z tabulky všechny záznamy. Mnohem častější bude situace, kdy chcete vybrat jen nějaké řádky a ty odstranit. O takové situaci platí to, co bylo řečeno v minulém díle. Lehce to shrňme. Příkaz DELETE může obsahovat klauzuli WHERE, která omezí mazané řádky na nějakou podmnožinu z celkového počtu pomocí podmínek. Lze tedy například napsat:
delete * from faktury
where cena = 500;
delete from zakaznik where id = 156;
Rovněž lze omezit maximální počet řádků, které bude třeba smazat, pomocí klauzule LIMIT. Má-li být smazán nejvýše jeden řádek, lze tedy přepsat příkazy výše ve smyslu:
delete * from faktury
where cena = 500 limit 1;
delete from zakaznik where id = 156 limit 1;
Moc doplňujících informací se k příkazu DELETE napsat nedá. Má
pochopitelně nějaké ty přepínače, o nichž je zmínka v manuálu.
DELETE však není jediný způsob, jak v MySQL odstraňovat záznamy.
TRUNCATE TABLE je příkaz, který odstraňuje všechny záznamy v tabulce, přičemž definici tabulky samotné ponechává. Následující dva příkazy budou tedy totožné:
delete from faktury;
truncate table faktury;
Proč tedy existují na jednu akci dva různé příkazy? Především proto,
že příkaz TRUNCATE je mnohem rychlejší. Jelikož ví, že bude muset
smazat celou tabulku, nemusí tento příkaz procházet a mazat řádky po
jednom. U extrémně velkých tabulek je toto zrychlení markantní. Tento
příkaz však nevrací počet odstraněných řádků.
Se samotným mazáním řádků v tabulkách obyčejně problémy nebývají.
Otázka však je, jak smazání ovlivní data nebo aplikace, které s daty
pracují. Potíž je v tom, že jednou smazaný řádek již nelze nijak
obnovit. Další pozoruhodná potíž spočívá v tom, že data v jedné
tabulce mohou souviset s daty v tabulce jiné (o tom ještě v seriálu
uslyšíme). Ukažme si tedy, jak se to dá v praxi obejít.
Pozn.: Vnímavý čtenář namítne, že i
smazaný záznam lze obnovit, pokud je operace součástí transakce. To je
pravda. Zmíníme se o tom jindy. Rovněž je pravda, že data v
souvisejících tabulkách lze
efektivně spravovat pomocí referenční integrity. Nicméně, obecný
problém s mazáním nic z toho úplně neřeší.
Stornovací záznamy
Představte si na chvíli, že došlo k chybě v nějakém bankovním systému a
nedopatřením vám někdo odečetl prostředky z běžného účtu. Mohlo se tak
stát pomocí následujícího příkazu MySQL:
insert into
pohyby_na_uctu (ucet, datum, castka) values ('123456', '2005-04-25
12:00:00', -50000);
Právě byste zchudli o 50 000,- Kč. Jenomže na chybu by se přišlo. Běžně v takových situacích nedochází k tomu, že by se záznam o odečtení prostředků prostě vymazal - to by totiž vedlo k tomu, že už se nikdo nedozví, co se vlastně stalo. Namísto příkazu:
delete from
pohyby_na_uctu where ucet='123456' and datum = '2005-04-25 12:00:00'
and castka = -50000 limit 1;
tedy dojde nejspíš ke vložení dalšího záznamu s opačnou hodnotou částky:
insert into
pohyby_na_uctu (ucet, datum, castka) values ('123456', '2005-04-25
12:10:00', 50000);
Příznaky
Někdy je k vidění následující technika: Řádky se fyzicky neodstraňují,
místo toho se jim nastaví hodnota nějakého zvlášť k tomu určeného
sloupce (příznaku) a nechají se být. Nevýhoda tohoto přístupu spočívá
pochopitelně v tom, že s tím musejí aplikace počítat; výhoda na druhou
stranu je ta, že "smazání" lze kdykoli vrátit zpět. Namísto příkazu:
delete from knihy where
rok_zakoupeni = 1999;
by se v aplikaci používající tuto techniku zapsalo něco ve smyslu:
update knihy set deleted
= 1 where rok_zakoupeni = 1999;
Pokud byste si to chtěli do budoucna rozmyslet, můžete provést další
příkaz UPDATE. Aplikace by pochopitelně musela počítat s tím, že nesmí
vracet všechny knihy, ale jen ty, které NEMAJÍ nastavenou jedničku ve
sloupci DELETE.
Přesun jinam
To je další oblíbená možnost: Záznam je sice z požadované tabulky
smazán, ale je přemístěn do jiné tabulky, která slouží jako archiv. S
vědomostmi, které jsme v tomto seriálu zatím načerpali, bychom to mohli
napsat pomocí dvojice příkazů INSERT a DELETE nějak takto:
create table if not
exists archiv_knih like knihy;
insert into archiv_knih select * from knihy where rok_zakoupeni = 1999;
delete from knihy where rok_zakoupeni = 1999;
Výhody a nevýhody? V databázi se bude skladovat mnohem více
tabulkek, což je nevýhodné. Ale každý smazaný záznam bude v archivu,
což je zase velmi výhodné. Tabulka, do níž se v takovém případě
přesouvá, by měla mít stejnou strukturu jako tabulka, z níž se bude
mazat. Pomocí CREATE TABLE ... LIKE je velmi jednoduché toho dosáhnout.
Logování
Je rovněž možné si někam (třeba do jiné tabulky) ukládat záznamy o
datu, čase a uživateli, který něco smazal. Tento postup sice nevede k
tomu, že by se smazaný řádek dal nějak odstranit, nicméně vede k tomu,
že je alespoň možné zjistit, kdo smazání provedl.
V příštím díle našeho seriálu se podíváme na některé speciality,
které provázejí příkazy pro manipulaci s daty.