Re: One parent record with 3 possible child records - Mailing list pgsql-sql

From Nic Mitchell
Subject Re: One parent record with 3 possible child records
Date
Msg-id ee6dc985-9d57-42bd-a3bc-28c716c184f9@cam.ac.uk
Whole thread Raw
In response to One parent record with 3 possible child records  (JORGE MALDONADO <jorgemal1960@gmail.com>)
List pgsql-sql
On 02/05/2024 00:08, JORGE MALDONADO wrote:
> Hi,
> 
> I have one table that can have relations to only 1 of 3 possible tables. 
> For example: tblMain*,* tblOne, tblTwo and tblThree.
> 
> I will always have 1 record in tblMain but each record in this table 
> will be related to one record in tblOne OR one record in tblTwo OR one 
> record in tblThree.
> 
> The relation between tblMain and tblOne is 1:1.
> The relation between tblMain and tblTwo is 1:1.
> The relation between tblMain and tblThree is 1:1.
> 
> Is it better to set tblMain as parent or child?
> 
> This can be seen as if tblOne, tblTwo and tblThree 
> extend tblMain depending on a specific criteria.
> 
> Let's say that tableMain has a string field called "type" with the 
> following possible values: "residential", "industrial" and "energy".
> 
> I will always insert a record in tblMain but:
> * If type is "residential" then a record in tblOne is created and it is 
> associated to tblMain,
> * If type is "industrial" a record in tblTwo is created and it is 
> associated to tblMain
> * If type is "energy" a record in tblThree is created and it is 
> associated to tblMain.
> 
> I am not sure how to design a case like this. I will very much 
> appreciate your feedback.
> 
> Best regards,
> Jorge Maldonado
> 

I worked with a similar looking, I think, relationship for a time. The 
idea was that, using trigger functions, rows in the _object table - your 
tblMain - would be inserted/deleted only ever as a result of 
inserting/deleting rows in the tables _objecttype[1-3] - your tblOne, 
tblTwo and tblThree.

I came up with this attempting to solve a problem where I needed to be 
able to model groups that could contain objects of different types, each 
of which had to be stored in their own table.

So, here's the code...

CREATE TABLE public._objecttype (
    _id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 10001 ),
    _name text NOT NULL,
    CONSTRAINT _objecttype_pkey PRIMARY KEY (_id),
    CONSTRAINT _objecttype__name_key UNIQUE (_name)
);

COMMENT ON TABLE public._objecttype IS E'values in _name column will be 
_objectype1,  _objectype2, and _objectype3';

CREATE TABLE public._object (
    _id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 20001 ),
    _objecttype_id integer NOT NULL,
    CONSTRAINT _object_pkey PRIMARY KEY (_id)
);

CREATE TABLE public._objecttype1 (
    _object_id integer NOT NULL,
    _name text NOT NULL,
    CONSTRAINT _objecttype1_pkey PRIMARY KEY (_object_id),
    CONSTRAINT _objecttype1__name_key UNIQUE (_name)
);

CREATE TABLE public._objecttype2 (
    _object_id integer NOT NULL,
    _name text NOT NULL,
    CONSTRAINT _objecttype2_pkey PRIMARY KEY (_object_id),
    CONSTRAINT _objecttype2__name_key UNIQUE (_name)
);

CREATE TABLE public._objecttype3 (
    _object_id integer NOT NULL,
    _name text NOT NULL,
    CONSTRAINT _objecttype3_pkey PRIMARY KEY (_object_id),
    CONSTRAINT _objecttype3__name_key UNIQUE (_name)
);

CREATE FUNCTION public._tf_biu_createobject ()
    RETURNS trigger
    LANGUAGE plpgsql
    AS $$
begin
if NEW._object_id is NULL then
    WITH object_id AS (
     INSERT INTO _object (_objecttype_id)
     VALUES (
        (
        SELECT _objecttype._id
        FROM _objecttype
        WHERE _objecttype._name
        LIKE TG_TABLE_NAME
        )
    )
     RETURNING _id)
     SELECT * FROM object_id INTO NEW._object_id;
end if;
return NEW;
end;
$$;

CREATE TRIGGER _t_biu_createobject
    BEFORE INSERT OR UPDATE
    ON public._objecttype1
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_biu_createobject();

CREATE TRIGGER _t_biu_createobject
    BEFORE INSERT OR UPDATE
    ON public._objecttype2
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_biu_createobject();

CREATE TRIGGER _t_biu_createobject
    BEFORE INSERT OR UPDATE
    ON public._objecttype3
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_biu_createobject();

CREATE FUNCTION public._tf_ad_deleteobject ()
    RETURNS trigger
    LANGUAGE plpgsql
    AS $$
begin
   DELETE FROM _object
   WHERE _object._id = OLD._object_id;
   return NULL;
end
$$;

CREATE TRIGGER _t_ad_deleteobject
    AFTER DELETE
    ON public._objecttype1
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_ad_deleteobject();

CREATE TRIGGER _t_ad_deleteobject
    AFTER DELETE
    ON public._objecttype2
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_ad_deleteobject();

CREATE TRIGGER _t_ad_deleteobject
    AFTER DELETE
    ON public._objecttype3
    FOR EACH ROW
    EXECUTE PROCEDURE public._tf_ad_deleteobject();

ALTER TABLE public._object ADD CONSTRAINT _object__objecttype_id_fkey 
FOREIGN KEY (_objecttype_id)
REFERENCES public._objecttype (_id) MATCH SIMPLE
ON DELETE RESTRICT ON UPDATE NO ACTION;

ALTER TABLE public._objecttype1 ADD CONSTRAINT 
_objecttype1__object_id_fkey FOREIGN KEY (_object_id)
REFERENCES public._object (_id) MATCH SIMPLE
ON DELETE RESTRICT ON UPDATE NO ACTION;

ALTER TABLE public._objecttype2 ADD CONSTRAINT 
_objecttype2__object_id_fkey FOREIGN KEY (_object_id)
REFERENCES public._object (_id) MATCH SIMPLE
ON DELETE RESTRICT ON UPDATE NO ACTION;

ALTER TABLE public._objecttype3 ADD CONSTRAINT 
_objecttype3__object_id_fkey FOREIGN KEY (_object_id)
REFERENCES public._object (_id) MATCH SIMPLE
ON DELETE RESTRICT ON UPDATE NO ACTION;








pgsql-sql by date:

Previous
From: Sanjay Minni
Date:
Subject: Re: One parent record with 3 possible child records
Next
From: Feike Steenbergen
Date:
Subject: Re: How to pass arguments in postgres to sql scripts.