Можно ли при обновлении каскадировать с действием, определяемым справочной таблицей? - PullRequest
0 голосов
/ 31 августа 2018

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 не передается в таблицу консультантов по ссылкам. И, даже если он действительно был передан в таблицу консультантов, таблица консультантов также имеет свои ограничения уникальности, наложенные на специальный внешний ключ.

Для гуру, есть ли способ сделать это:

  1. Обновление первых дочерних таблиц специальности: Обновление консультанта set speciality_recid = recid 'Внутренняя медицина'
  2. Немедленно во время обновления таблицы консультантов, пусть таблица консультантов выполнит действие, которое проверяет новое значение. То есть, если новое значение приводит к существующей записи, то таблица консультанта должна будет каскадно передать своим дочерним элементам правильный recid , а затем удалить запись, которая привела к нарушению уникальности.

  3. После того, как все обновления будут каскадными, и до того, как произойдет нарушение уникальности, удалите измененную запись.

Следовательно, существует ли способ при обновлении каскада, который позволяет каждой из ссылочных таблиц решать, какие (если таковые имеются) свои собственные ключи необходимо каскадировать и / или удалять записи?

Редактировать: можно ли использовать здесь "Обновить правило"?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...