SQL ON DELETE CASCADE

Index, feed.

[ Date | 2026-02-28 23:32 -0500 ]

Let’s create a queries table, and a queries_reports table that holds a list of reports for each record in queries:

Initial settings

Different databases and clients will have different defaults and settings available. Here are the settings use for this post, using the sqlite3 client.

-- Used to render tables for this post
.mode markdown

-- SQLite doesn't enforce constraints by default. Enable checking
-- with:
PRAGMA foreign_keys = ON;

Foreign key without ON DELETE1

CREATE TABLE queries (id TEXT PRIMARY KEY);
CREATE TABLE queries_reports (
  query_id TEXT NOT NULL
    REFERENCES queries,
  report_id TEXT NOT NULL,
  PRIMARY KEY (query_id, report_id)
);

At this point, thanks to REFERENCES query2, we are not allowed to insert a record into queries_reports that refers to a non-existent query:

sqlite> INSERT INTO queries_reports (query_id, report_id) VALUES
   ...>   ('query0', 'report0');
Error: FOREIGN KEY constraint failed

Creating records with matching IDs in queries beforehand, on the other hand, works:

INSERT INTO queries (id) VALUES ('query0'), ('query1');

INSERT INTO queries_reports (query_id, report_id) VALUES
   ('query0', 'report0'),
   ('query0', 'report1'),
   ('query1', 'report0'),
   ('query1', 'report1');
sqlite> SELECT * FROM queries;

id
query0
query1
sqlite> SELECT * FROM queries_reports;

query_id report_id
query0 report0
query0 report1
query1 report0
query1 report1

Deleting a query that has a reference from queries_reports does not work:

sqlite> DELETE FROM queries WHERE id = 'query0';
Error: FOREIGN KEY constraint failed

Deleting referencing rows from queries_reports first lets us delete from queries:

DELETE FROM queries_reports WHERE query_id = 'query0';
DELETE FROM queries WHERE id = 'query0';
sqlite> SELECT * FROM queries;

id
query1
sqlite> SELECT * FROM queries_reports;

query_id report_id
query1 report0
query1 report1

Notes:

ON DELETE CASCADE

We alter the definition for table queries_reports as follows to add ON DELETE CASCADE (keeping the same create statement for queries and the same two insert statements):

CREATE TABLE queries_reports (
  query_id TEXT NOT NULL
    REFERENCES queries ON DELETE CASCADE,
  report_id TEXT NOT NULL,
  PRIMARY KEY (query_id, report_id)
);

At this point, the contents of the two tables are:

Deleting from queries silently deletes matching rows from queries_reports:

sqlite> DELETE FROM queries WHERE id = 'query0';
# Succesful.

Final state of the tables:


  1. When a foreign-key constraint does not specify an ON DELETE action, the default is NO ACTION. [pgsql-ddl-constraints][Postgres documentation] has more explanation and examples.↩︎

  2. When no column is mentioned after the referenced table’s name, this implicitly means that table’s primary key; in this case queries.id.↩︎

www.kurokatta.org


www.kurokatta.org

Quick links:

Photos
Montréal
Oregon
Paris
Camp info 2007
Camp Faécum 2007
--more--
Doc
Jussieu
Japanese adjectives
Muttrc
Bcc
Montréal
Couleurs LTP
French English words
Petites arnaques
--more--
Hacks
Statmail
DSC-W17 patch
Scarab: dictionnaire de Scrabble
Sigpue
Recipes
Omelette soufflée au sirop d'érable
Camembert fondu au sirop d'érable
La Mona de Tata Zineb
Cake aux bananes, au beurre de cacahuètes et aux pépites de chocolat
*