这就是我想出的。
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();
我在没有触发器的情况下在两个表中使用外键尝试了 Igor 的版本。在这种情况下,此约束不会被延迟。
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;
我明白了:错误:“address_id”列中的空值违反非空约束
使用此匿名块插入时:
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
$$;
使用地址表(Igor 版本)的 address_id 强制参与 member_details 的另一个问题是,这允许我将行插入 member_details 并引用现有地址行,但现有地址行引用不同的 member_details 行。当后面的 member_details 行被删除时,它会级联并删除地址行,地址行可以或不能删除(取决于设置)新插入的 member_details 行。当加入 member_id 和 address_id 时,它也会返回不同的详细信息。因此,它需要另一个约束,所以我一直使用触发器并在插入之前删除它并在插入之后重新创建它,因为触发器没有被延迟。