Questo è quello che mi viene in mente.
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();
Ho provato la versione di Igor utilizzando chiavi esterne in entrambe le tabelle senza i trigger. In questo caso questo vincolo non è 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;
ottengo questo: ERRORE: valore nullo nella colonna "address_id" viola vincolo non nullo
Inserendo utilizza questo blocco 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
$$;
altro problema di far rispettare partecipazione obbligatoria member_details using address_id della tabella indirizzi (versione di Igor) è che questo mi permette di inserire una riga in member_details e fare riferimento a una riga di indirizzo esistente, ma la riga di indirizzo esistente fa riferimento a una riga member_details diversa. Quando viene eliminata la seconda riga member_details, esegue la cascata ed elimina la riga dell'indirizzo, che può o non può eliminare (dipende dalle impostazioni) la nuova riga member_details inserita. Restituirebbe anche diversi dettagli quando si unisse su member_id e su address_id. Pertanto, richiede un altro vincolo, quindi sono rimasto con il trigger e lo abbiamo rilasciato prima dell'inserto e lo ho ricreato dopo l'inserimento, poiché il trigger non è differito.
Il tuo corrente 'member_in_has_address()' restituirà 'true' quando ** qualsiasi ** dei membri ha indirizzo. Non controllerà se un determinato membro ha un indirizzo. –
Grazie, Igor, ma la mia domanda principale è come differire tale vincolo finché il bambino ('indirizzo') non viene aggiornato. L'inserto è il seguente: inserire in 'member_details' che è padre e poi a' address' che ha la chiave di prua. 'member_details' ha la partecipazione obbligatoria con' address'. –
Vedere la mia risposta qui sotto. La risposta: crea una chiave esterna defferrata. –