4. blokk · Módosítás és törlés · 8. témakör
A DELETE sorokat töröl egy táblából. Egyszerű utasítás — mégis
itt esik a legtöbb végzetes hiba: egy elfelejtett WHERE az
egész táblát kiürítheti. Megnézzük a biztonságos törlést, az idegen kulcsok
védelmét, és a DELETE/TRUNCATE/DROP különbségét — élő gyakorlóval.
A DELETE a DML (adatmanipuláció) része, akárcsak
az INSERT és az UPDATE. Egész sorokat távolít el a táblából — nem egyes
oszlopértékeket (azokat az UPDATE módosítja). A tábla szerkezete (oszlopai) megmarad, csak a
benne lévő adatok fogynak.
A DELETE mindig teljes sorokat töröl. Ha csak egy oszlop értékét akarod „kitörölni”, azt az
UPDATE … SET oszlop = NULL teszi (a következő témakör).
A leggyakoribb forma: megadjuk a táblát, és egy WHERE feltétellel
azt, mely sorokat töröljük. Csak azok a sorok törlődnek, amelyekre a feltétel
igaz:
-- A 7-es azonosítójú termék törlése: DELETE FROM termek WHERE id = 7; -- A "torolve" állapotú rendelések törlése: DELETE FROM rendeles WHERE statusz = 'torolve';
A WHERE ugyanúgy működik, mint a SELECT-nél: használhatsz
=, <, >,
AND, OR, IN,
LIKE, BETWEEN operátorokat.
Ha elhagyod a WHERE-t, a DELETE a tábla
ÖSSZES sorát törli. Nincs „biztos vagy benne?” kérdés — azonnal
végrehajtódik.
-- ⚠ VESZÉLY: ez a tábla MINDEN sorát törli! DELETE FROM termek; -- A termek tábla üres lesz. Visszavonni csak mentésből lehet.
Mielőtt DELETE-et futtatsz, győződj meg róla, hogy ott van a
WHERE, és pontosan azt szűri, amit akarsz! Egy elgépelt vagy
hiányzó feltétel éles adatbázison azonnali, visszafordíthatatlan adatvesztést okoz. Sok
DELETE-hiba abból ered, hogy valaki a feltételt csak később akarta hozzáírni.
-- Több feltétel: DELETE FROM termek WHERE keszlet = 0 AND ar < 1000; -- Beágyazott lekérdezéssel: töröljük a rendelés nélküli vásárlókat DELETE FROM vasarlo WHERE id NOT IN (SELECT vasarlo_id FROM rendeles);
Bevált szokás: futtasd le előbb ugyanazzal a WHERE-rel egy
SELECT-et
(SELECT * FROM termek WHERE …), nézd meg, pontosan mely sorok
jönnének, és csak ha stimmel, cseréld a SELECT *-ot
DELETE-re.
Az idegen kulcsok megvédik az adatok épségét törléskor is. Ha egy sorra hivatkozik egy másik tábla (pl. a vásárlóhoz tartozik rendelés), akkor a vásárló nem törölhető csak úgy — különben „árva” rendelések maradnának.
DELETE FROM vasarlo WHERE id = 1; -- Hiba: Cannot delete or update a parent row: -- a foreign key constraint fails (a vásárlónak van rendelése)
Hogy mi történjen ilyenkor, azt az idegen kulcs ON DELETE
szabálya dönti el (lásd a CREATE témakört):
| ON DELETE szabály | Mi történik a szülő törlésekor |
|---|---|
RESTRICT / NO ACTION | Megtiltja a törlést, amíg van rá hivatkozó gyermeksor (ez az alapértelmezett). |
CASCADE | A szülővel együtt a gyermeksorok is automatikusan törlődnek. |
SET NULL | A gyermek idegen kulcsa NULL-ra áll (ha az oszlop engedi a NULL-t). |
RESTRICT esetén a törlést „alulról felfelé” végezd: előbb a gyermeksorokat (pl.
rendeles_tetel, majd rendeles), és
csak utána a szülőt (vasarlo).
Három különböző „törlés” létezik — fontos, hogy ne keverd őket:
| DELETE | TRUNCATE | DROP | |
|---|---|---|---|
| Mit töröl | Sorokat (WHERE-rel szűrhető) | Az összes sort (gyorsan) | Az egész táblát (szerkezetestül) |
| WHERE? | Igen | Nem | Nem |
| Megmarad a tábla? | Igen | Igen | Nem |
| Csoport | DML | DDL | DDL |
-- A cim tábla gyors kiürítése — a szerkezet megmarad, az id-számláló 1-re áll vissza: TRUNCATE TABLE cim; -- (DELETE FROM cim; után a számozás folytatódna — TRUNCATE után elölről indul.)
Vigyázat: olyan táblát, amelyre idegen kulcs hivatkozik (a webshopban pl.
vasarlo, termek,
rendeles), a TRUNCATE nem enged kiüríteni —
hibát ad akkor is, ha a hivatkozó tábla éppen üres. Az ilyen táblák kiürítése
DELETE-tel megy, a helyes (alulról felfelé) sorrendben.
A TRUNCATE MySQL-parancs; az alábbi SQLite-gyakorló nem ismeri
(ott a tábla kiürítése DELETE FROM tabla-val történik). Ha
kipróbálod, a gyakorló jelzi.
Éles adatbázison a törlés mindig kockázat. Néhány bevált védelem:
START TRANSACTION /
BEGIN, és ha valami nem stimmel,
ROLLBACK-kel visszavonod; ha jó,
COMMIT-tal véglegesíted.-- Tranzakcióval védve: ha mégsem jó, visszavonjuk BEGIN; DELETE FROM termek WHERE keszlet = 0; -- ... ellenőrzöd; ha hibás: ROLLBACK; -- visszavonja a törlést -- ha rendben volt: COMMIT; (véglegesít)
A Workbench alapból bekapcsolt „safe updates” móddal dolgozik: a kulcs nélküli (WHERE nélküli) DELETE/UPDATE-et el sem futtatja, hanem Error Code: 1175 hibát ad. Ha egyszer szándékosan kell WHERE nélkül törölnöd, a védelmet ideiglenesen kikapcsolhatod — de utána mindig kapcsold vissza:
-- 1. A védelem kikapcsolása (0 = kikapcsolva): SET SQL_SAFE_UPDATES = 0; -- 2. Most már lefut a WHERE nélküli törlés is: DELETE FROM rendeles_tetel; -- 3. A védelem visszakapcsolása (1 = bekapcsolva) — ne maradjon kikapcsolva! SET SQL_SAFE_UPDATES = 1;
A SET SQL_SAFE_UPDATES csak az aktuális kapcsolat
(munkamenet) beállítását módosítja — újracsatlakozás után ismét a Workbench saját
beállítása él (Edit → Preferences → SQL Editor → Safe Updates).
Próbáld ki a törlést a webshopon! Itt be van kapcsolva az idegenkulcs-ellenőrzés, így láthatod az FK-védelmet működés közben. Ha „elrontasz” valamit, az Adatok újratöltése gomb mindent visszaállít.
A motor SQLite-alapú, bekapcsolt idegenkulcs-ellenőrzéssel. A DELETE, a
WHERE és a tranzakció (BEGIN/ROLLBACK)
azonos a MySQL-lel. A TRUNCATE viszont MySQL-specifikus — ha
kipróbálod, a gyakorló jelzi. (Internetkapcsolat szükséges a motorhoz.)
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás — a kódírós feladatokat futtasd is le a fenti élő gyakorlóban!
Írd le fejből a DELETE alap szerkezetét (sablonként)!
Mi a bevált első lépés egy törlés előtt, hogy ne törölj rosszat?
Sorold fel a három ON DELETE szabályt, és röviden, mit
tesznek!
Mit csinál ez az utasítás?
DELETE FROM rendeles WHERE statusz = 'torolve';
Miért veszélyes ez, és hogyan javítanád?
DELETE FROM termek
Mit töröl ez a lekérdezés? (Gondolj a 7d. témakör NOT IN csapdájára is!)
DELETE FROM vasarlo WHERE id NOT IN (SELECT vasarlo_id FROM rendeles);
Kódírás: töröld azt a terméket, amelynek a neve pontosan „Régi USB hub”!
Kódírás: töröld azokat a termékeket, amelyek kifogytak (keszlet = 0) és olcsóbbak 1000 Ft-nál!
Kódírás: tranzakcióval töröld a „torolve” állapotú rendeléseket, de
építsd be a visszavonás lehetőségét (ROLLBACK)! Ellenőrizd
SELECT COUNT(*)-gal a törlés előtti és utáni állapotot.
Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.
| Fogalom | Jelentés |
|---|---|
| DELETE | teljes sorok törlése (DML) — a tábla szerkezete megmarad |
| WHERE nélküli DELETE | a tábla ÖSSZES sorát törli — a leggyakoribb végzetes hiba |
| „előbb SELECT” minta | ugyanazzal a WHERE-rel előbb SELECT — ellenőrzés törlés előtt |
| FK-védelem · árva sor | hivatkozott szülő sor nem törölhető, hogy ne maradjon árva gyermek |
| ON DELETE szabályok | RESTRICT (tilt) · CASCADE (továbbgyűrűztet) · SET NULL (NULL-ra állít) |
| TRUNCATE | a tábla gyors kiürítése (DDL) — AUTO_INCREMENT nullázódik, nem visszavonható; hivatkozott (szülő) táblára hibát ad |
| DROP | a teljes tábla megszüntetése szerkezetestül |
| tranzakció | BEGIN → műveletek → ROLLBACK (visszavon) vagy COMMIT (véglegesít) |
| safe updates mód | a Workbench védelme a kulcs nélküli DELETE/UPDATE ellen — kapcsolója: SET SQL_SAFE_UPDATES = 0 / 1 |
DELETE teljes sorokat töröl (DML); a tábla szerkezete
megmarad.DELETE FROM tabla WHERE feltétel; — csak az illeszkedő sorok
törlődnek.ON DELETE szabály (RESTRICT / CASCADE / SET NULL) dönt.SET SQL_SAFE_UPDATES = 0/1), mentés.