PostgreSQL 10.1
После полной нормализации моих таблиц у меня теперь есть важные части информации, однозначно помеченные ссылками между таблицами.
Теперь проблема в том, как правильно «объединить» разные деревья записей. В качестве примера у меня есть следующие определения таблиц:
CREATE TABLE speciality
(
recid integer NOT NULL DEFAULT nextval('speciality_recid_seq'::regclass),
speciality_name text COLLATE pg_catalog."default" NOT NULL,
modified timestamp without time zone DEFAULT now(),
CONSTRAINT speciality_pkey PRIMARY KEY (recid),
CONSTRAINT speciality_name_key UNIQUE (speciality_name)
)
CREATE TABLE consultant
(
recid integer NOT NULL DEFAULT nextval('consultant_recid_seq'::regclass),
lastname text COLLATE pg_catalog."default" NOT NULL,
firstname text COLLATE pg_catalog."default" NOT NULL,
modified timestamp without time zone DEFAULT now(),
speciality_recid integer NOT NULL,
CONSTRAINT consultant_pkey PRIMARY KEY (recid),
CONSTRAINT consultant_unique UNIQUE (lastname, firstname, speciality_recid),
CONSTRAINT consultant_speciality_recid_fkey FOREIGN KEY (speciality_recid)
REFERENCES nova.speciality (recid) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT non_empty_firstname CHECK (length(firstname) > 0),
CONSTRAINT non_empty_lastname CHECK (length(lastname) > 0)
)
CREATE TABLE referral_doctor
(
recid integer NOT NULL DEFAULT nextval('referral_doctor_recid_seq'::regclass),
consultant_recid integer,
orderno integer,
office_recid integer,
modified timestamp without time zone NOT NULL DEFAULT now(),
CONSTRAINT referral_doctor_pkey PRIMARY KEY (recid),
CONSTRAINT referral_doctor_consultant_recid_fkey FOREIGN KEY (consultant_recid)
REFERENCES nova.consultant (recid) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT referral_doctor_office_recid_fkey FOREIGN KEY (office_recid)
REFERENCES nova.office (recid) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE RESTRICT,
CONSTRAINT referral_doctor_orderno_fkey FOREIGN KEY (orderno)
REFERENCES nova.orders (orderno) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
)
Важным моментом является то, что таблица консультантов ссылается на recid таблицы специальности, а referral_doctor ссылается на recid таблицы консультантов. Все хорошо.
Проблема. Допустим, что в таблице специальностей есть две определенные записи с уникальными именами «Кардиология» и «Внутренняя медицина». Со временем разные записи консультантов будут ссылаться на эти две специальности, а рефералы будут иметь были сделаны врачам, специализирующимся в этих двух областях.
Теперь АМА решает, что «Кардиология» действительно должна быть «Внутренняя медицина»:).
Как изменить запись "Кардиология" в таблице специальности на "Внутренняя медицина", если эти записи ограничены, чтобы быть уникальными? Кроме того, таблица консультантов использует внешний ключ speciality_recid, чтобы сделать консультанта уникальным. То есть при изменении speciality_recid таблицы специальности также будет иметь место нарушение уникальности в таблице консультанта! Тогда, даже если это будет решено, таблица рефералов теперь должна будет ссылаться на другую запись в таблице консультантов!
Насколько я понимаю, первичные и уникальные столбцы немедленно проверяются при обновлении строки . Таким образом,
Update speciality
set speciality_name = 'Internal Medicine'
where speciality_name = 'Cardiology'
немедленно потерпит неудачу из-за УНИКАЛЬНОГО ограничения. Делая
With t as (
Update speciality
set recid = 'Internal Medicine' recid
where recid = 'Cardiology' recid
)
Delete from speciality
where speciality name ='Cardiology'
Также происходит сбой, так как удаление происходит перед обновлением cte (если оно есть), поэтому «новый» recid не передается в таблицу консультантов по ссылкам. И, даже если он действительно был передан в таблицу консультантов, таблица консультантов также имеет свои ограничения уникальности, наложенные на специальный внешний ключ.
Для гуру, есть ли способ сделать это:
- Обновление первых дочерних таблиц специальности:
Обновление консультанта
set speciality_recid = recid 'Внутренняя медицина'
Немедленно во время обновления таблицы консультантов, пусть таблица консультантов выполнит действие, которое проверяет новое значение. То есть, если новое значение приводит к существующей записи, то таблица консультанта должна будет каскадно передать своим дочерним элементам правильный recid , а затем удалить запись, которая привела к нарушению уникальности.
После того, как все обновления будут каскадными, и до того, как произойдет нарушение уникальности, удалите измененную запись.
Следовательно, существует ли способ при обновлении каскада, который позволяет каждой из ссылочных таблиц решать, какие (если таковые имеются) свои собственные ключи необходимо каскадировать и / или удалять записи?
Редактировать: можно ли использовать здесь "Обновить правило"?