🗑 Setting Foreign Keys to NULL on Delete (ON DELETE SET NULL)
As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021.
With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences.
In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS.
I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.
In the previous lesson, we tested:
🔥
ON DELETE CASCADE
When we deleted a user, all their related photos were automatically deleted.
Now we’re going to explore a very different behavior:
🟡
ON DELETE SET NULL
Instead of deleting related records…
we simply remove the relationship.
🏗 Step 1: Drop the Photos Table Again
To test a new delete behavior, we reset our table:
DROP TABLE photos;
This completely removes the table and its data.
🧱 Step 2: Recreate Photos Table with ON DELETE SET NULL
Now we recreate the table — but this time we add:
ON DELETE SET NULL
Here’s the full SQL:
CREATE TABLE photos (
id SERIAL PRIMARY KEY,
url VARCHAR(200),
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL
);
⚠ Important:
If we try to insert photos tied to a user that no longer exists (like user ID 1, which we deleted earlier), we will get a foreign key error.
So for this test, we insert photos tied to an existing user (for example, user ID 4).
📦 Sample Data
Let’s say our database looks like this:
Users
| id | username |
| 2 | pfeffer |
| 3 | 99stroman |
| 4 | sim3onis |
Photos
| id | url | user_id |
| 6 | http://img6.jpg | 3 |
| 7 | http://img7.jpg | 4 |
| 8 | http://img8.jpg | 4 |
Notice:
👉 User 4 has two photos.
💣 Step 3: Delete the User
Now we delete user 4:
DELETE FROM users
WHERE id = 4;
The deletion succeeds.
But what happens to the photos?
🔍 Step 4: Check the Photos Table
SELECT * FROM photos;
Result:
| id | url | user_id |
| 6 | http://img6.jpg | 3 |
| 7 | http://img7.jpg | NULL |
| 8 | http://img8.jpg | NULL |
The photos were NOT deleted.
Instead:
👉 Their user_id column was automatically set to NULL.
🧠 What Just Happened?
Because we defined:
ON DELETE SET NULL
PostgreSQL did this:
Delete user 4
Find all photos referencing user 4
Set their
user_idvalue toNULL
The relationship is removed —
but the photo record remains.
🆚 CASCADE vs SET NULL
| Behavior | Result |
| ON DELETE CASCADE | Delete dependent records |
| ON DELETE SET NULL | Keep records, remove relationship |
🎯 When Would We Use SET NULL?
This is useful when:
🚫 Banning a User
You delete a problematic user account
But you want to keep their posts/photos visible.
📦 Preserving Historical Data
You remove the parent record
But child data still has value.
📰 Content Platforms
A user gets deleted
But their published content remains public.
⚠ Important Requirement
For SET NULL to work:
The foreign key column must allow NULL values.
If you define:
user_id INTEGER NOT NULL
Then ON DELETE SET NULL will fail.
💡 Mental Model
Think of it like this:
CASCADE → Destroy everything connected
SET NULL → Disconnect but keep the data
🏁 What’s Next?
We’ve now tested:
✅ CASCADE
✅ SET NULL
Next up:
🟢
ON DELETE SET DEFAULT
Where instead of deleting or nulling —
we assign a predefined default value.