Vai al contenuto principale

SQL ON DELETE RESTRICT: previeni la perdita accidentale di dati

Scopri come SQL ON DELETE RESTRICT protegge l’integrità dei dati. Impara come blocca le eliminazioni non sicure e quando sceglierlo rispetto alle regole CASCADE o SET NULL.
· 10 min leggi

Scopri con l'IA

Eliminare dati in SQL di solito non è semplice come rimuovere una singola riga. Nelle basi di dati relazionali, le tabelle sono spesso collegate e l’eliminazione di un record in una può avere un impatto su un’altra tabella. 

SQL fornisce la clausola ON DELETE, che definisce cosa deve accadere quando viene eliminata una riga referenziata. Dopo la clausola ON DELETE, puoi specificare cosa succede, ad esempio bloccare l’eliminazione, rimuovere automaticamente la riga dipendente o aggiornare i dati referenziati.

In questo tutorial ti mostrerò il vincolo ON DELETE RESTRICT, che impedisce l’eliminazione di una riga padre se esistono ancora righe figlie dipendenti. Tratterò anche in dettaglio come funziona il vincolo, perché i database lo applicano e quando è la scelta giusta rispetto ad altre regole di eliminazione. Infine, se cerchi il comportamento opposto — dove l’eliminazione di una riga padre rimuove automaticamente i record correlati — consulta la nostra guida su SQL ON DELETE CASCADE.

Cos’è ON DELETE RESTRICT in SQL?

Il vincolo ON DELETE RESTRICT in SQL è una funzione di sicurezza del database. Garantisce che non puoi eliminare un record “padre” se esistono ancora record “figli” che lo puntano.

Nota: mentre database come PostgreSQL e MySQL supportano direttamente la parola chiave RESTRICT, SQL Server applica lo stesso comportamento di restrizione usando invece ON DELETE NO ACTION.

Integrità referenziale e chiavi esterne

L’integrità referenziale è il principio secondo cui le relazioni tra tabelle devono rimanere valide in ogni momento. Le chiavi esterne lo fanno imponendo che i valori in una tabella figlia corrispondano a righe esistenti in una tabella padre. Per esempio, un DepartmentID nella tabella Employees potrebbe fare riferimento a uno specifico ID nella tabella Departments.

Pertanto, le regole di DELETE in SQL esistono perché rimuovere una riga padre può rompere questa relazione. Il database ha bisogno di istruzioni chiare su se bloccare l’eliminazione, eseguirla in cascata o applicare un’altra azione alle righe dipendenti.

Cosa significa davvero RESTRICT

Quando definisci una chiave esterna con ON DELETE RESTRICT, il database verifica l’esistenza di righe figlie correlate prima di eseguire un’eliminazione. Se esiste un record figlio, l’operazione di eliminazione viene rifiutata automaticamente.  In questo caso, RESTRICT impedisce l’eliminazione invece di modificare i dati, come vedremo più avanti nel tutorial.

Come funziona ON DELETE RESTRICT in SQL

Per capire come funziona il vincolo ON DELETE RESTRICT, è utile vedere come il database valuta le eliminazioni passo dopo passo durante una transazione.

Relazioni tra tabelle padre e figlie

In SQL, la tabella padre contiene i record principali, mentre la tabella figlia contiene i record dipendenti. Per esempio, il tuo database può avere una tabella padre Categories con un category_id “Electronics”. La tabella figlia Products avrà un record “Smartphone”, quindi collegato alla tabella padre tramite category_id.

Quando esegui un comando DELETE sulla tabella padre, il motore del database analizza immediatamente tutte le tabelle figlie associate per verificare se qualche riga punta a quello specifico ID padre.

Cosa succede quando provi a eliminare righe soggette a restrizioni?

Se provi a eliminare una riga padre che è ancora referenziata, il database interrompe l’operazione e genera un errore. Questo messaggio di errore indica una violazione di un vincolo di chiave esterna.

Questo comportamento è intenzionale: ti obbliga a decidere consapevolmente se eliminare o aggiornare prima le righe figlie dipendenti, oppure a rivalutare se la riga padre debba essere rimossa.

SQL ON DELETE RESTRICT vs. altre regole di eliminazione

In un DBMS, esistono regole specifiche che governano come i dati possono essere eliminati da tabelle correlate. In questa sezione confronteremo il vincolo ON DELETE RESTRICT con le regole di eliminazione comuni in SQL, così potrai vedere chiaramente come ognuna influisce sui dati correlati.

RESTRICT vs. CASCADE in SQL

Il vincolo RESTRICT in SQL blocca l’eliminazione della riga padre se righe figlie la referenziano, evitando perdite accidentali di dati. La query seguente mostra come implementare RESTRICT durante la definizione dello schema della tabella. Impedisce di eliminare un cliente se esistono ordini che lo referenziano.

-- Parent table
CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    name VARCHAR(100)
);

-- Child table with ON DELETE RESTRICT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE RESTRICT
);

Tuttavia, il vincolo CASCADE in SQL fa sì che un’eliminazione rimuova automaticamente tutte le righe figlie dipendenti. Nell’esempio seguente, CASCADE consente l’eliminazione automatica di tutti gli ordini associati a un cliente quando il record del cliente viene eliminato.

-- Child table with ON DELETE CASCADE
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE CASCADE
);

RESTRICT vs. SET NULL e SET DEFAULT

I vincoli SET NULL e SET DEFAULT in SQL preservano le righe figlie ma cambiano come esse referenziano il padre.

Per esempio, nella query qui sotto, quando un cliente viene eliminato, il customer_id negli ordini correlati viene impostato a NULL, mantenendo i record degli ordini ma rimuovendo il collegamento al cliente.

-- Child table using SET NULL
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT NULL,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE SET NULL
);

Se usi il vincolo SET DEFAULT, quando un cliente viene eliminato, il customer_id negli ordini correlati è impostato sul suo valore predefinito, preservando i record degli ordini e assegnando loro un valore segnaposto predefinito.

-- Child table using SET DEFAULT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT DEFAULT 0,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE SET DEFAULT
);

Creare chiavi esterne con ON DELETE RESTRICT in SQL

Per implementare il vincolo ON DELETE RESTRICT in SQL, devi definirlo quando crei la relazione tra due tabelle.

Definire RESTRICT negli schemi delle tabelle

Puoi specificare il comportamento di eliminazione in SQL quando crei la tabella o aggiungerlo successivamente se la tua tabella esiste già.

L’esempio qui sotto mostra come usare il vincolo di chiave esterna ON DELETE RESTRICT nell’istruzione CREATE TABLE quando definisci una nuova tabella in SQL.

-- Stores department details
CREATE TABLE departments (
    department_id INT PRIMARY KEY, 
    department_name VARCHAR(100)
);

-- -- Prevents deleting a department with employees
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,      -- Unique employee identifier
    department_id INT, 
    CONSTRAINT fk_employees_departments
        FOREIGN KEY (department_id)
        REFERENCES departments(department_id)
        ON DELETE RESTRICT 
);

La query seguente aggiunge la stessa regola di chiave esterna a una tabella employees esistente con l’istruzione ALTER TABLE in SQL, per impedire l’eliminazione di reparti che sono ancora referenziati dai dipendenti.

-- Adds a foreign key constraint after the table already exists
ALTER TABLE employees
ADD CONSTRAINT fk_employees_departments
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
ON DELETE RESTRICT;    -- Blocks deletion of departments that have employees

Comportamento predefinito di eliminazione in SQL

In molti sistemi di database popolari, come SQL Server, PostgreSQL e MySQL, RESTRICT è il comportamento predefinito. Se definisci una chiave esterna senza specificare alcuna clausola ON DELETE, il database in genere si comporterà come se avessi scritto ON DELETE NO ACTION o ON DELETE RESTRICT. Questo design del motore assicura che tu riceva un errore anziché eliminare accidentalmente grandi quantità di dati correlati.

Casi d’uso comuni per ON DELETE RESTRICT in SQL

Nello scenario reale, il vincolo ON DELETE RESTRICT in SQL si applica dove l’integrità dei dati richiede un controllo esplicito prima delle eliminazioni.

Proteggere i dati di riferimento critici

Il vincolo RESTRICT è comunemente usato per tabelle che rappresentano dati di riferimento fondamentali, come utenti, account, prodotti o valori di lookup. Questi record sono spesso condivisi in più parti del sistema, e eliminarli automaticamente potrebbe causare perdite di dati diffuse o incongruenze.

Per esempio, eliminare un utente che possiede ancora ordini, log di audit o permessi di solito non è sicuro. Con il vincolo ON DELETE RESTRICT in SQL, il database blocca l’eliminazione e ti obbliga a risolvere prima tali dipendenze, preservando l’integrità dei dati storici e transazionali.

Applicare flussi di pulizia espliciti

Il vincolo RESTRICT è utile anche quando vuoi che la pulizia sia intenzionale e tracciabile. Costringe sviluppatori e amministratori a gestire i dati in modo deliberato. Invece di lasciare che il database elimini automaticamente i record, il vincolo RESTRICT ti obbliga a rivedere i dati dipendenti per decidere se eliminare le righe figlie, riassegnarle a un nuovo padre o annullare l’operazione.

Risoluzione dei problemi di DELETE causati da RESTRICT in SQL

Quando il vincolo ON DELETE RESTRICT blocca un’eliminazione, l’errore risultante può confondere se non te lo aspetti. Capire questi errori ti aiuta a risolverli in sicurezza.

Comprendere gli errori di violazione dei vincoli

Quando provi a eliminare una riga padre che è ancora referenziata, il database genera una violazione di vincolo di chiave esterna. Ecco come appare il messaggio nei diversi sistemi di database:

  • PostgreSQL: ERROR: update or delete on table "parent_table" violates foreign key constraint "fk_name" on table "child_table"

  • MySQL: Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails…

  • SQL Server: The DELETE statement conflicted with the REFERENCE constraint "FK_Name". The conflict occurred in database "DBName", table "dbo.ChildTable", column 'ParentID'.

In tutti i database, il messaggio di errore indicherà quanto segue:

  • Quale vincolo di chiave esterna è stato violato
  • Quale tabella funge da figlia
  • Quale valore chiave è ancora referenziato

Risoluzione sicura delle eliminazioni bloccate

Se ricevi il messaggio di errore di un’eliminazione bloccata ma intendevi eliminare la riga padre, ti consiglio una delle seguenti opzioni:

Elimina prima il record figlio: se i dati dipendenti non servono più, esegui prima un’istruzione DELETE sulle righe figlie e poi elimina il record padre.

-- Step 1: Remove dependencies
DELETE FROM Orders WHERE CustomerID = 501; 
-- Step 2: Now the parent delete will work
DELETE FROM Customers WHERE CustomerID = 501;

Aggiorna i riferimenti delle figlie: se vuoi mantenere le righe figlie ma rimuovere il padre, aggiorna le righe figlie per fare riferimento a un ID padre diverso.

-- Reassign orders to a "General" customer account (ID 999)
UPDATE Orders SET CustomerID = 999 WHERE CustomerID = 501;

Modifica il vincolo: in rari scenari amministrativi, puoi disabilitare temporaneamente i controlli delle chiavi esterne. È un’operazione rischiosa che può portare a corruzione dei dati se non gestita con estrema attenzione.

Note e comportamenti specifici del database

Sebbene il concetto di vincolo ON DELETE RESTRICT sia standard tra i database SQL, i motori gestiscono in modo leggermente diverso il timing e la logica interna.

Comportamento di PostgreSQL, MySQL e SQL Server

In PostgreSQL, MySQL e SQL Server il vincolo ON DELETE RESTRICT impedisce l’eliminazione di una riga padre quando esistono righe figlie correlate. Tuttavia, questi motori presentano le seguenti piccole differenze sintattiche:

MySQL: segue rigorosamente i vincoli RESTRICT di SQL. Se non specifichi una regola, il comportamento predefinito è RESTRICT.

-- MySQL: RESTRICT is the default if no rule is specified
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
);

PostgreSQL: supporta sia i vincoli RESTRICT sia NO ACTION. Sebbene si comportino quasi in modo identico, RESTRICT è strettamente immediato, mentre NO ACTION consente controlli differiti.

-- PostgreSQL: NO ACTION (can be deferred)
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE NO ACTION
);

SQL Server: usa il vincolo NO ACTION come equivalente al comportamento standard di RESTRICT. Non utilizza esplicitamente la parola chiave RESTRICT nella sintassi T-SQL, ma ottiene lo stesso risultato impedendo l’eliminazione.

-- SQL Server: Uses NO ACTION instead of RESTRICT
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    CONSTRAINT fk_orders_customers
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        ON DELETE NO ACTION
);

Ti consiglio di seguire i corsi Introduction to SQL Server e Creating PostgreSQL Databases per aprendere di più sulle differenze tra i dialetti SQL quando si creano database.

Vincoli differiti e comportamento delle transazioni

In configurazioni avanzate, come in PostgreSQL o Oracle, potresti incontrare vincoli differiti. Ciò significa che il vincolo viene verificato al momento del commit della transazione, anziché immediatamente quando viene eseguita l’istruzione DELETE.

In tali sistemi, un’eliminazione che normalmente verrebbe bloccata da RESTRICT può sembrare riuscire temporaneamente all’interno di una transazione, salvo poi fallire al momento del commit. Questo consente operazioni complesse e multi-step, come eliminare e reinserire dati correlati nella stessa transazione, pur applicando l’integrità alla fine.

Il nostro Introduction to Oracle SQL ti aiuterà a comprendere meglio come Oracle elabora le query.

Scegliere la strategia ON DELETE giusta

Selezionare il vincolo corretto ti aiuta a trovare un equilibrio tra integrità dei dati e usabilità dell’applicazione. Considera gli scenari seguenti per scegliere il metodo appropriato con la clausola ON DELETE.

Quando RESTRICT è la scelta più sicura

Usa il vincolo ON DELETE RESTRICT in SQL quando:

  • I dati sono molto preziosi: i record padre sono importanti e ampiamente referenziati nel database.

  • È richiesta una revisione manuale: vuoi imporre che una persona o un flusso logico di business decida cosa fare con i dati dipendenti.

  • Prevenire eliminazioni “silenziose”: vuoi assicurarti che uno sviluppatore non cancelli accidentalmente migliaia di righe con un singolo CASCADE delete.

Ti suggerisco di provare lo skill track SQL Server for Database Administrators se progetti o mantieni regolarmente database nel tuo lavoro. 

Quando considerare alternative

Dove il vincolo RESTRICT potrebbe essere troppo rigido per il tuo sistema, valuta le seguenti opzioni:

  • Usa il vincolo CASCADE quando il record figlio non ha significato senza il record padre.

  • Usa il vincolo SET NULL quando la relazione è opzionale.

  • Usa il vincolo SET DEFAULT quando hai un “segnaposto” che deve ereditare tutti i record orfani per mantenere il sistema fluido.

Conclusione

Il vincolo ON DELETE RESTRICT in SQL è una regola di chiave esterna protettiva che privilegia l’integrità dei dati rispetto alla comodità, bloccando l’eliminazione delle righe padre quando esistono ancora record figli dipendenti. Incoraggiando strategie di pulizia intenzionali e una chiara responsabilità delle operazioni di eliminazione, il vincolo RESTRICT agisce come una funzione di sicurezza nel design relazionale. Come buona pratica, scegli sempre le regole di eliminazione SQL in base alla logica di business e alla semantica dei dati, invece di affidarti alla comodità o a esigenze a breve termine.

Ti consiglio di seguire il nostro corso Database Design, dove imparerai a creare e gestire database e a selezionare il DBMS più adatto alle tue esigenze. Ti consiglio anche di provare il nostro percorso di carriera Associate Data Engineer in SQL per imparare le basi dell’ingegneria dei dati e del data warehousing.  

Allan Ouko

Autore

Allan Ouko

Technical writer di Data Science con esperienza pratica in data analytics, business intelligence e data science. Scrivo contenuti pratici e orientati al settore su SQL, Python, Power BI, Databricks e data engineering, basati su lavoro di analytics reale. La mia scrittura unisce profondità tecnica e impatto sul business, aiutando i professionisti a trasformare i dati in decisioni sicure.

SQL ON DELETE RESTRICT - Domande frequenti

Qual è la differenza tra RESTRICT e NO ACTION?

Nella maggior parte dei database si comportano allo stesso modo. RESTRICT verifica immediatamente, mentre NO ACTION può essere verificato al termine dell’istruzione o della transazione.

Cosa succede quando provo a eliminare una riga padre soggetta a RESTRICT?

L’operazione di DELETE fallisce e il database genera un errore di violazione del vincolo di chiave esterna.

In cosa ON DELETE RESTRICT è diverso da ON DELETE CASCADE?

RESTRICT blocca completamente l’eliminazione, mentre CASCADE elimina automaticamente tutte le righe figlie dipendenti.

Come risolvo un’operazione di DELETE bloccata da ON DELETE RESTRICT?

Come risolvo un’operazione di DELETE bloccata da ON DELETE RESTRICT?

Posso modificare una chiave esterna esistente per usare ON DELETE RESTRICT?

Sì. Puoi eliminare e ricreare il vincolo di chiave esterna con ON DELETE RESTRICT usando ALTER TABLE.

Argomenti

Correlato