Это то, что я придумал.
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();
Я попробовал версию Игоря, используя внешние ключи в обеих таблицах без триггеров. В этом случае это ограничение не делит.
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» нарушает не-нулевое ограничение
При установке с помощью этого annonymous блок:
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','[email protected]','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
$$;
Еще одна проблема, с соблюдения обязательного участия в member_details с использованием address_id таблицы адресов (версия Игоря) заключается в том, что это позволяет мне вставлять строку в member_details и ссылаться на существующую строку адреса, но существующая строка адреса ссылается на другую строку member_details. Когда последняя строка member_details удаляется, она каскадирует и удаляет строку адреса, которая может или не может удалить (зависит от настроек) новую вставленную строку member_details. Он также будет возвращать различные детали при присоединении к member_id и адресу address. Следовательно, для этого требуется другое ограничение, поэтому я остался с триггером и отбрасывал его перед вставкой и воссозданием его после вставки, поскольку триггер не откладывается.
Ваш текущий 'member_in_has_address()' будет возвращать 'true', когда ** любой ** из членов имеет адрес. Он не проверяет, имеет ли конкретный член адрес. –
Спасибо, Игорь, но мой главный вопрос заключается в том, как уменьшить такое ограничение до тех пор, пока ребенок ('address') не будет обновлен. Вставка выглядит следующим образом: вставляем в 'member_details', который является родительским, а затем' address', который имеет ключ foreigh. 'member_details' имеет обязательное участие в' address'. –
См. Мой ответ ниже. Ответ - создать дефферентированный внешний ключ. –