Course
Deleting data in SQL is usually not as simple as removing a single row. In relational databases, tables are often connected, and deleting a record in one can have an impact on another table.
SQL provides the ON DELETE clause, which defines what should happen when a referenced row is deleted. After the ON DELETE clause, you can specify what happens, such as blocking the delete, automatically removing the dependent row, or updating the referenced data.
In this tutorial, I will show you the ON DELETE RESTRICT constraint, which prevents the deletion of a parent row if any dependent child rows still exist. I will also cover extensively how the constraint works, why databases enforce it, and when it’s the right choice compared to other delete rules. Finally, if you’re looking for the opposite behavior — where deleting a parent row automatically removes related records — see our guide on SQL ON DELETE CASCADE.
What Is ON DELETE RESTRICT in SQL?
The ON DELETE RESTRICT constraint in SQL is a database safety feature. It ensures that you cannot delete a "parent" record if there are "child" records still pointing to it.
Note: While databases like PostgreSQL and MySQL support the RESTRICT keyword directly, SQL Server enforces the same restriction behavior using ON DELETE NO ACTION instead.
Referential integrity and foreign keys
Referential integrity is the principle that relationships between tables must remain valid at all times. Foreign keys enforce this by requiring that values in a child table correspond to existing rows in a parent table. For example, a DepartmentID in the Employees table might reference a specific ID in the Departments table.
Therefore, SQL DELETE rules exist because removing a parent row can break this relationship. The database needs clear instructions on whether to block the delete, cascade it, or apply another action to dependent rows.
What RESTRICT actually means
When you define a foreign key with ON DELETE RESTRICT, the database checks for related child rows before executing a delete. If a child record exists, the delete operation is rejected automatically. In this case, RESTRICT stops the deletion from happening rather than modifying the data, as we will see later in the tutorial.
How ON DELETE RESTRICT Works in SQL
To understand how the ON DELETE RESTRICT constraint works, you need to see how the database evaluates deletes step by step during a transaction.
Parent and child table relationships
In SQL, the parent table holds the primary records, while the child table holds the dependent records. For example, your database may have a parent table Categories with a category_id of “Electronics.” The child table Products will have a record “Smartphone”, then linked to the parent table using the category_id.
When you run a DELETE command on the parent table, the database engine immediately scans all associated child tables to see if any rows are pointing to that specific parent ID.
What happens when you try to delete restricted rows?
If you attempt to delete a parent row that is still referenced, the database stops the operation and raises an error. This error message indicates a violation of a foreign key constraint.
This behavior is intentional, forcing you to make a conscious decision to either delete or update the dependent child rows first, or reconsider whether the parent row should be removed at all.
The SQL ON DELETE RESTRICT vs. Other Delete Rules
In a DBMS, there are specific rules that govern how data can be deleted from related tables. In this section, we will compare the ON DELETE RESTRICT constraint with the common delete rules in SQL, so you can clearly see how each one affects related data.
RESTRICT vs. CASCADE in SQL
The SQL RESTRICT constraint blocks parent row deletion if child rows reference it, ensuring no accidental data loss. The following query shows how to implement RESTRICT when defining the table schema. It prevents deleting a customer if there are any orders that reference that customer.
-- 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
);
However, the SQL CASCADE constraint ensures that a deletion automatically deletes all dependent child rows. In the example below, CASCADE allows the automatic deletion of all orders associated with a customer when the customer record is deleted.
-- 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 and SET DEFAULT
The SQL SET NULL and SET DEFAULT constraints preserve child rows but change how they reference the parent.
For example, in the query below, when a customer is deleted, the customer_id in related orders is set to NULL, keeping the order records but removing the link to the customer.
-- 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
);
If you use the SET DEFAULT constraint, when a customer is deleted, the customer_id in related orders is set to its default value, preserving the order records while assigning them a predefined placeholder value.
-- 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
);
Creating Foreign Keys with ON DELETE RESTRICT in SQL
To implement the ON DELETE RESTRICT constraint in SQL, you need to define it when you create the relationship between two tables.
Defining RESTRICT in table schemas
You can specify the delete behavior in SQL when creating the table or add it afterwards if your table already exists.
The example below shows how to use the SQL ON DELETE RESTRICT foreign key constraint in the CREATE TABLE statement when defining a new table 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
);
The query below adds the same foreign key rule to an existing employees table in the SQL ALTER TABLE statement, to prevent the deletion of departments that are still referenced by employees.
-- 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
Default delete behavior in SQL
In many popular database systems, such as SQL Server, PostgreSQL, and MySQL, RESTRICT is the default behavior. If you define a foreign key without specifying any ON DELETE clause, the database will usually act as if you wrote ON DELETE NO ACTION or ON DELETE RESTRICT. This database engine design ensures you receive an error rather than accidentally delete large amounts of related data.
Common Use Cases for ON DELETE RESTRICT in SQL
In real-world scenarios, the SQL ON DELETE RESTRICT constraint is applied where data integrity demands explicit oversight before deletions.
Protecting critical reference data
The SQL RESTRICT constraint is commonly used for tables that represent core reference data, such as users, accounts, products, or lookup values. These records are often shared across multiple parts of the system, and deleting them automatically could result in widespread data loss or inconsistencies.
For example, deleting a user who still owns orders, audit logs, or permissions is usually unsafe. With the SQL ON DELETE RESTRICT constraint, the database blocks the delete and forces you to resolve those dependencies first, preserving the integrity of historical and transactional data.
Enforcing explicit cleanup workflows
The SQL RESTRICT constraint is also useful when you want cleanup to be intentional and traceable. It forces developers and administrators to be deliberate about how they handle data. Instead of letting the database automatically delete records, the RESTRICT constraint forces you to review the dependent data to decide whether to delete the child records, reassign them to a new parent, or cancel the operation.
Troubleshooting DELETE Errors Caused by RESTRICT in SQL
When the ON DELETE RESTRICT constraint blocks a delete, the resulting error can be confusing if you’re not expecting it. Understanding these errors helps you resolve them safely.
Understanding constraint violation errors
When you attempt to delete a parent row that is still referenced, the database raises a foreign key constraint violation. The following is how the message will appear in different database systems:
-
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 all the databases, the error message will indicate the following:
- Which foreign key constraint was violated
- Which table is acting as the child
- Which key value is still being referenced
Safely resolving blocked deletes
If you get the error message of a blocked delete, but you wanted to delete the parent row, I recommend using any of the following options:
Delete the child record first: If the dependent data is no longer needed, run a DELETE statement on the child rows first, then delete the parent record.
-- Step 1: Remove dependencies
DELETE FROM Orders WHERE CustomerID = 501;
-- Step 2: Now the parent delete will work
DELETE FROM Customers WHERE CustomerID = 501;
Update child references: If you want to retain the child rows but remove the parent, update the child rows to reference a different parent ID.
-- Reassign orders to a "General" customer account (ID 999)
UPDATE Orders SET CustomerID = 999 WHERE CustomerID = 501;
Change the constraint: In rare administrative scenarios, you may temporarily disable foreign key checks. This is a risky operation that can lead to data corruption if not handled with extreme care.
Database-Specific Notes and Behavior
While the concept of the ON DELETE RESTRICT constraint in SQL is standard across SQL databases, different engines handle the timing and internal logic slightly differently.
PostgreSQL, MySQL, and SQL Server behavior
In PostgreSQL, MySQL, and SQL Server, the ON DELETE RESTRICT constraint prevents deleting a parent row when related child rows exist. However, these engines have the following minor syntax differences:
MySQL: Strictly follows the SQL RESTRICT constraints. If you don't specify a rule, it defaults to 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: Supports both RESTRICT and NO ACTION constraints. While they behave almost identically, RESTRICT is strictly immediate, whereas NO ACTION allows for deferred checks.
-- 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: Uses NO ACTION constraint as its equivalent to the standard RESTRICT behavior. It does not explicitly use the keyword RESTRICT in its T-SQL syntax, but achieves the same result by preventing the delete.
-- 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
);
I recommend taking our Introduction to SQL Server and Creating PostgreSQL Databases courses to learn more about the differences in the SQL dialects when creating databases.
Deferred constraints and transaction behavior
In advanced database configurations, such as in PostgreSQL or Oracle, you may encounter deferred constraints. This means that the constraint is checked at transaction commit time, rather than immediately when the DELETE statement is executed.
In such systems, a delete that would normally be blocked by RESTRICT may appear to succeed temporarily within a transaction, only to fail when you attempt to commit. This allows for complex, multi-step operations, such as deleting and reinserting related data within the same transaction, while still enforcing integrity at the end.
Our Introduction to Oracle SQL course will help you further understand how Oracle processes queries.
Choosing the Right ON DELETE Strategy
Selecting the correct constraint helps you strike a balance between data integrity and application usability. Consider the following scenarios to help you choose the appropriate method with the ON DELETE clause.
When RESTRICT is the safest choice
Use the SQL ON DELETE RESTRICT constraint when:
-
The data is highly valuable: The parent records are important and widely referenced in the database.
-
Manual review is required: You want to force a human or a specific business logic flow to decide what happens to dependent data.
-
Preventing “Silent” deletions: You want to ensure that a developer doesn't accidentally wipe out thousands of rows with a single
CASCADEdelete.
I suggest you try out the SQL Server for Database Administrators skill track if you regularly design or maintain databases as part of your work.
When to consider alternatives
Where the RESTRICT constraint might be too rigid for your system, consider the following options:
-
Use the
CASCADEconstraint when the child record has no meaning without the parent record. -
Use the
SET NULLconstraint when the relationship is optional. -
Use the
SET DEFAULTvconstraint when you have a “placeholder” that should inherit all orphaned records to keep the system running smoothly.
Conclusion
The SQL ON DELETE RESTRICT constraint is a protective foreign key rule that prioritizes data integrity over convenience by blocking the deletion of parent rows when dependent child records still exist. By encouraging deliberate cleanup strategies and clear ownership of delete operations, SQL RESTRICT constraint acts as a safety feature in relational design. As a best practice, always choose SQL delete rules based on business logic and data semantics, rather than defaulting to convenience or short-term needs.
I recommend taking our Database Design course, where you will learn to create and manage databases and select the appropriate DBMS for your needs. I also recommend trying out our Associate Data Engineer in SQL career track to learn the fundamentals of data engineering and data warehousing.
SQL ON DELETE RESTRICT FAQs
What’s the difference between RESTRICT and NO ACTION?
In most databases, they behave the same. RESTRICT checks immediately, while NO ACTION may be checked at statement or transaction end.
What happens when I try to delete a restricted parent row?
The DELETE operation fails, and the database raises a foreign key constraint violation error.
How is ON DELETE RESTRICT different from ON DELETE CASCADE?
RESTRICT blocks the delete entirely, while CASCADE automatically deletes all dependent child rows.
How do I resolve a DELETE blocked by ON DELETE RESTRICT?
How do I resolve a DELETE blocked by ON DELETE RESTRICT?
Can I change an existing foreign key to use ON DELETE RESTRICT?
Yes. You can drop and recreate the foreign key constraint with ON DELETE RESTRICT using ALTER TABLE.

