Transakce
Některé změny patří k sobě. Nová objednávka je řádek v tabulce objednavky a řádek v tabulce polozky pro každou její hru. Co když se objednávka uloží a pak se něco pokazí dřív, než se uloží její položky? ID hry je špatně, aplikace spadne, server přijde o proud. Obchod pak má objednávku, ve které nic není. Takové změny se musí provést všechny, nebo žádná.
Právě k tomu slouží transakce. BEGIN (začni) ji zahájí a změny po něm jsou její součástí. COMMIT (potvrď) ji ukončí a uloží všechny její změny najednou. Objednávka hry Goal Rush pro Martina Zemana, bezpečně:
BEGIN;
INSERT INTO objednavky (zakaznik_id, datum, stav)
VALUES (14, '2026-01-08', 'zaplaceno');
INSERT INTO polozky (objednavka_id, hra_id, pocet, cena)
VALUES (31, 8, 1, 1299);
COMMIT;Až do COMMIT změny nikdo jiný nevidí: ostatní uživatelé databáze vidí obchod takový, jaký byl před BEGIN. Pak uvidí všechny změny najednou, nikdy jen jejich polovinu. A když se uprostřed něco pokazí, aplikace transakci místo toho ukončí příkazem ROLLBACK (vrať zpět), který vrátí všechny změny od BEGIN, jako by se nikdy nestaly. Napůl hotová objednávka zmizí.
Uvnitř transakce své vlastní změny vidíte, takže ji můžete použít i k tomu, abyste něco vyzkoušeli, podívali se na výsledek a vzali to zpátky:
BEGIN;
DELETE FROM recenze;
SELECT COUNT(*) AS recenze
FROM recenze;
ROLLBACK;
SELECT COUNT(*) AS recenze
FROM recenze;| recenze |
|---|
| 0 |
| recenze |
|---|
| 25 |
První dotaz nenajde žádnou recenzi, druhý zase všech 25: ROLLBACK je vrátil.
Bez BEGIN je každý příkaz malou transakcí sám o sobě. Proto UPDATE, který uprostřed selže, nezmění nic, jak jste viděli u cen. Transakce totéž zajistí pro několik příkazů dohromady. (V jiných databázích můžete místo BEGIN potkat také START TRANSACTION.)
V tomto kurzu začíná každé spuštění s čerstvou databází, takže rozdíl, který COMMIT dělá, neuvidíte, ale ve skutečné databázi je to on, kdo změny uloží natrvalo. Typická chyba: zapomenutý COMMIT. Vaše vlastní dotazy změny vidí, takže všechno vypadá v pořádku, ale když se aplikace od databáze odpojí, databáze nedokončenou transakci vrátí a změny jsou pryč. Tady na to přijdete u dalšího BEGIN: transakce nemůže začít uvnitř jiné, takže BEGIN skončí chybou cannot start a transaction within a transaction. A COMMIT bez BEGIN je také chyba: cannot commit - no transaction is active (nelze potvrdit, žádná transakce neběží).
Jak psát:
Pokyny
Filip Beneš (zákazník 12) zadává 2026-01-15 svou první objednávku: jeden kus Star Pilots (hra 7) a jeden Cube Logic (hra 6), každý za cenu z tabulky hry. V jedné transakci přidejte objednávku se stavem zaplaceno (její ID se doplní samo a bude to 31) a její dvě položky a transakci potvrďte.
Pod tím ukažte, co je v objednávce 31: název každé hry, počet kusů a cenu, seřazené podle názvu:
| nazev | pocet | cena |
|---|---|---|
| Cube Logic | 1 | 129 |
| Star Pilots | 1 | 899 |
Filip chce objednat ještě Robot Rebellion. Zahajte novou transakci, přidejte jeho druhou objednávku (s datem 2026-01-16 a stavem zaplaceno) a ukažte ID a datum všech Filipových objednávek, seřazené podle ID. Robot Rebellion ale ještě nevyšla, takže ji obchod prodat nemůže: transakci vraťte zpět a ukažte jeho objednávky znovu stejným dotazem. Výsledky mají být tyto dva:
| id | datum |
|---|---|
| 31 | 2026-01-15 |
| 32 | 2026-01-16 |
| id | datum |
|---|---|
| 31 | 2026-01-15 |
Začněte programovat zdarma
8/9