MySQL [eshop]> call delete_product("kaffe1");
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (eshop.stock, CONSTRAINT stock_ibfk_1 FOREIGN KEY (prod_id) REFERENCES product (id))
Bakgrunden är ett krav i databas kmom05 om CRUD av produkter i en eshop.
Skapa CRUD för att lägga till, redigera, visa och radera produkter. Du behöver enbart redigera de delar som finns i tabellen kopplad till produkten. Du behöver inte redigera antal produkter på lagret, eller kopplingen till kategori.
Du kan inte göra delete på en produkt om den finns i lagret, eller i en order, därav felmeddelandet som påpekar att du har en FK constraint där produkten du försöker radera finns i lagret.
Om du verkligen vill ta bort produkten så måste först ta bort den på lagret och alla andra platser den finns på. Detta kan du göra genom att skriva en lagrad procedur som gör det, eller genom att erbjuda ett GUI där användaren själv kan utföra radering av alla förekomster av produkten, eller implementera ON DELETE CASCADE som gör det automatiskt åt dig.
I found a solution. SET FOREIGN_KEY_CHECKS = 0; is this ok?
Nej, det är inte en bra lösning. Det ignorerar de kontroller som FK ger dig och det är en fix som leder till att din databas blir inkonsistent.
Risken med att ta bort en produkt, och alla dess förekomster, är att din databas bli logiskt korrupt eller inkonsistent. Det är normalt sett inte logiskt att ta bort orderrader på gamla ordrar, bara för att du vill radera en produkt.
Ett bra alternativ, i detta fallet, är att använda konceptet SOFT DELETE där man istället för en riktig DELETE bara markerar produkten som raderad via ett värde i en kolumn, tex en tidsstämpel. Detta förklaras i artikeln "Använd TIMESTAMP för status i databastabellen".
Man kan även tolka kravet som att "det går inte" göra DELETE på produkt om den redan är använd. Det är en tolkning som inte ger Ux på inlämningen. Du kan skriva i din redovisningstext "det var så jag tolkade kravet och jag kände att det var en rimlig avgränsning givet tid/engagement/etc".
Summering
Den rätta vägen (databasmässigt, logiskt och begreppsmässigt) är en soft delete.
När du väl har lagt till en produkt och börjat använda den i lagret/order så har den satt sina spår i databasen. Du kan inte ta bort alla dessa förekomster utan att göra din databas logiskt korrupt.
När du vill sluta använda en produkt, du tänker inte beställa den till lagret eller låta kunderna köpa den, då vill du göra den osynlig/soft deletad i systemet, du markerar den som "raderad" men du tar inte bort den. Du gör så att ditt GUI inte visar att produkten finns längre.
Men den som vill se dina gamla ordrar, där produkten köptes, kan fortfarande göra det.
Den enkla vägen tidsmässigt och för att klara kursmomentet, är att säga "när produkten är använd kan man inte göra DELETE på den, det är en begränsning i min implementation".
...
..:
.... /mos