Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CASCADE DELETE on two foreign key constraints

I have the following example:

Table A
   -some_id

Table B
   -another_id

Table C
   -some_id_fk
   -another_id_fk

I want to cascade a row on Table C if both some_id and another_id are deleted from their respective tables.

How can I make a row in Table C cascade itself when two foreign keys are deleted?

If only one of the FKs is deleted, the affected row should change to a null value in the column referencing that foreign key.

like image 714
12preschph Avatar asked Dec 19 '14 00:12

12preschph


People also ask

What is the purpose of applying on delete cascade in a foreign key constraint?

ON DELETE CASCADE constraint is used in MySQL to delete the rows from the child table automatically, when the rows from the parent table are deleted.

What does an on delete cascade clause imply in a foreign key?

A foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted.

Is Cascade a foreign key constraint?

A foreign key constraint on a stored generated column cannot use CASCADE , SET NULL , or SET DEFAULT as ON UPDATE referential actions, nor can it use SET NULL or SET DEFAULT as ON DELETE referential actions.


1 Answers

I suggest two foreign key constraints with ON DELETE SET NULL and a trigger that takes care of the rest

Tables:

CREATE TABLE a (a_id serial PRIMARY KEY, a text NOT NULL);
CREATE TABLE b (b_id serial PRIMARY KEY, b text NOT NULL);

CREATE TABLE ab (
  ab_id serial PRIMARY KEY
, a_id int REFERENCES a ON DELETE SET NULL
, b_id int REFERENCES b ON DELETE SET NULL
, UNIQUE (a_id, b_id)
);

Trigger:

CREATE OR REPLACE FUNCTION trg_ab_upbef_nulldel()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   DELETE FROM ab WHERE ab_id = NEW.ab_id;
   RETURN NULL;  -- to cancel UPDATE
END
$func$;

CREATE TRIGGER upbef_null2del
BEFORE UPDATE OF a_id, b_id ON ab
FOR EACH ROW
WHEN (NEW.a_id IS NULL AND NEW.b_id IS NULL)
EXECUTE PROCEDURE trg_ab_upbef_nulldel();

db<>fiddle here
Old sqlfiddle

Be sure to have a surrogate PK column for the connecting table. (a_id, b_id) cannot be the PK anyway, because that would disallow NULL in both. Add a UNIQUE constraint instead, which allows NULL values.

The trigger is optimized for performance and only kicks in when one of the two FK columns is updated, and only when that results in both being NULL.

The trigger function deletes the row and returns NULL to cancel the now void cascaded UPDATE.

like image 187
Erwin Brandstetter Avatar answered Nov 01 '22 20:11

Erwin Brandstetter