CodeGym /Corsi /SQL SELF /Uso di ON DELETE CASCADE e ON UPDATE...

Uso di ON DELETE CASCADE e ON UPDATE RESTRICT

SQL SELF
Livello 19 , Lezione 2
Disponibile

Immagina di aver creato un database dove c'è una tabella clienti (customers) e ordini (orders) collegati a questi clienti. Però, a un certo punto ti chiedi: cosa succede se un cliente viene eliminato dalla tabella customers? Anche i suoi ordini devono essere eliminati o rimarranno "orfani", cioè faranno riferimento a un cliente che non esiste più? E se invece vuoi cambiare l'ID del cliente? Qui entrano in gioco le operazioni a cascata (CASCADE) e le restrizioni (RESTRICT) per gestire il comportamento del database.

ON DELETE CASCADE è un meccanismo che elimina automaticamente i record collegati quando elimini un record dalla tabella principale. In altre parole, se elimini un cliente, anche tutti i suoi ordini verranno eliminati.

Funziona così: quando aggiungi ON DELETE CASCADE alla definizione della foreign key, il database "capisce" che anche il record collegato deve essere eliminato in automatico.

Esempio

Supponiamo di avere due tabelle: customers e orders. I clienti (customers) possono fare più ordini (orders), che corrisponde a una relazione ONE-TO-MANY. Vogliamo che, quando eliminiamo un cliente, anche tutti i suoi ordini vengano eliminati.

-- Creiamo la tabella clienti
CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- Creiamo la tabella ordini con una foreign key che punta alla tabella clienti
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE,
    order_date DATE NOT NULL
);

Inseriamo dati nelle tabelle

-- Inseriamo dati nella tabella clienti
INSERT INTO customers (name) VALUES ('Ivan'), ('Anna');

-- Inseriamo dati nella tabella ordini
INSERT INTO orders (customer_id, order_date) VALUES
(1, '2023-10-01'),
(1, '2023-10-02'),
(2, '2023-10-03');

Tabella orders:

order_id customer_id order_date
1 1 2023-10-01
2 1 2023-10-02
3 2 2023-10-03

Eliminiamo un cliente e vediamo cosa succede

-- Eliminiamo il cliente con ID 1
DELETE FROM customers WHERE customer_id = 1;

-- Vediamo cosa è rimasto nella tabella ordini
SELECT * FROM orders;
order_id customer_id order_date
3 2 2023-10-03

Come vedi, anche gli ordini collegati al cliente eliminato sono stati eliminati.

Limitare le modifiche: ON UPDATE RESTRICT

ON UPDATE RESTRICT ti permette di impedire la modifica di un valore nella tabella principale se c'è un record nella tabella figlia che fa riferimento a quel valore. È come una "barriera di protezione" che impedisce modifiche che potrebbero rompere l'integrità dei dati.

Come funziona? Quando aggiungi ON UPDATE RESTRICT, il database non ti permette di aggiornare la chiave nella tabella principale se ci sono record nella tabella figlia che la usano.

Esempio

Prendiamo sempre le stesse tabelle customers e orders, ma aggiungiamo una restrizione sull'aggiornamento della foreign key.

-- Ricreiamo la tabella ordini con la restrizione sull'aggiornamento
DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

Proviamo a cambiare l'ID del cliente

-- Tentativo di cambiare l'ID del cliente da 2 a 5
UPDATE customers 
SET customer_id = 5 
WHERE customer_id = 2;

Risultato:

ERROR:  update or delete on table "customers" violates foreign key constraint
DETAIL:  Key (customer_id)=(2) is still referenced from table "orders".

Come vedi, il database ha lanciato un errore perché la modifica della chiave avrebbe rotto il collegamento tra le tabelle.

Ti racconterò di più su UPDATE e le sue particolarità nel prossimo livello :P

Combinare ON DELETE CASCADE e ON UPDATE RESTRICT

Ovviamente, puoi combinare operazioni a cascata (CASCADE) e restrizioni (RESTRICT). Ad esempio, puoi impostare l'eliminazione automatica dei dati collegati quando elimini il record principale (ON DELETE CASCADE), ma allo stesso tempo impedire la modifica del suo ID (ON UPDATE RESTRICT), così eviti casini indesiderati.

Esempio

Creiamo di nuovo la tabella ordini usando entrambi i meccanismi:

DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
        ON DELETE CASCADE
        ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

Adesso:

  • Se elimini un cliente, tutti i suoi ordini vengono eliminati.
  • Se provi a cambiare l'ID del cliente, ricevi un errore.

Perché è importante nei progetti reali?

Usare CASCADE e RESTRICT è super importante nei sistemi grandi con tante tabelle collegate. Per esempio:

In un e-commerce, un cliente può avere degli ordini. Se il cliente decide di cancellare il suo profilo, non vuoi lasciare nel database ordini che non puntano più a niente. Qui ti aiuta ON DELETE CASCADE.

Allo stesso tempo, potresti voler impedire modifiche accidentali alle chiavi uniche, per non rompere i collegamenti tra le tabelle. Qui serve ON UPDATE RESTRICT.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION