This is what I come up with.
ALTER TABLE address
ADD CONSTRAINT address_member_in_has_address
FOREIGN KEY (member_id) REFERENCES member_details(member_id)
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED;
CREATE FUNCTION member_in_has_address() RETURNS trigger AS $BODY$
BEGIN
IF NOT EXISTS(SELECT *
FROM member_details
WHERE member_id IN (SELECT member_id
FROM address))
THEN
RAISE EXCEPTION 'Error: member does not have address';
END IF;
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
CREATE CONSTRAINT TRIGGER manatory_participation_member_details_ins
AFTER INSERT ON member_details
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE member_in_has_address();
CREATE CONSTRAINT TRIGGER manatory_participation_member_details_del
AFTER INSERT ON member_details
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE member_in_has_address();
I tried Igor's version using foreign keys in both tables without the triggers. In this case this constraint is not deffered.
ALTER TABLE member_details
ADD CONSTRAINT member_details_in_has_address
FOREIGN KEY (address_id) REFERENCES address
ON UPDATE NO ACTION ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED;
I get this: ERROR: null value in column "address_id" violates not-null constraint
When inserting using this annonymous block:
DO $$
DECLARE
mem BIGINT;
BEGIN
INSERT INTO member_details (member_first_name, member_last_name, member_dob, member_phone_no,
member_email, member_gender, industry_position, account_type, music_interests)
VALUES ('Rado','Luptak','07/09/80','07540962233','truba@azet.sk','M','DJ','basic','hard core');
SELECT member_id
INTO mem
FROM member_details
WHERE member_first_name = 'Rado' AND member_last_name = 'Luptak'
AND member_dob = '07/09/76';
INSERT INTO address (address_id, house_name_no, post_code, street_name, town, country, member_id)
VALUES (mem, '243', 'E17 3TT','Wood Road','London', 'UK', mem);
UPDATE member_details
SET address_id = mem WHERE member_id = mem;
END
$$;
Another problem with enforcing mandatory participation in member_details using address_id of address table (Igor's version) is that this allows me to insert row into member_details and reference an existing address row, but the existing address row references different member_details row. When the latter member_details row is deleted it cascades and deletes the address row, which can or cannot delete (depends on settings) the new inserted member_details row. It would also return different details when joining on member_id and on address_id. Therefore, it requires another constraint, so I stayed with trigger and dropping it before insert and recreating it after insert, due to the trigger is not deferred.