Antw: [SQL] Building "ON DELETE" rules to keep the referential integrity of a database

Gerhard Dieringer <dieringg@eba-haus.de>

From: "Gerhard Dieringer" <DieringG@eba-haus.de>
To: <genov@digsys.bg>
Cc: <pgsql-sql@postgresql.org>
Date: 1999-11-18T08:01:11Z
Lists: pgsql-sql
Stoyan Genov wrote:
> ...
> I would like also to build a rule which works on the "reverse DELETE"
> condition, and disallows deleting t1 records if there is a "child" in t2
> present.

> Does somebody have any ideas? Thanks in advance.


You can use ap pair of triggers to keep the referential integrity.

example:

create table master (
  mid    int4 not null,
  name   text);
create unique index master_idx on master(mid);

/* foreign key mid in detail references the primary key mid in master */
create table detail (
  did    int4 not null,
  name   text,
  mid    int4 not null);
create unique index detail_idx on detail(did);


/* allow PL/pgSQL procedures */
create function plpgsql_call_handler () returns opaque as
  '/usr/local/pgsql/lib/plpgsql.so' language 'C';

create trusted procedural language 'plpgsql'
  handler plpgsql_call_handler
  lancompiler 'PL/pgSQL';


/* handle delete and update in master */
create function del_master_fun () returns opaque as '
  declare
    id int4;
  begin 
    select did into id 
      from detail d
     where d.mid = old.mid;
    if found then
      raise exception ''cannot %'', tg_op;
    end if;
    if tg_op = ''DELETE'' then
      return old;
    else
      return new;
    end if;
  end;
' language 'plpgsql';

create trigger del_master_trg before delete or update on master
  for each row execute procedure del_master_fun();


/* handle insert and update in detail */
create function ins_detail_fun () returns opaque as '
  declare
    id int4;
  begin 
    select mid into id 
      from master m
     where m.mid = new.mid;
    if not found then
      raise exception ''cannot %'', tg_op;
    end if;
    return new;
  end;
' language 'plpgsql';

create trigger ins_detail_trg before insert or update on detail
  for each row execute procedure ins_detail_fun();

I hope this will help you.

Gerhard