Проверьте все связанные строки в PostgreSQL - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть база данных PostgreSQL [10.5] с довольно богатой схемой. У меня есть таблица CUSTOMER_CONTACT, на которую ссылается ряд других таблиц. Отношения представляют собой смесь delete cascade и delete restrict.

Я хочу предложить пользователю возможность удалить контакт с клиентом, если ни одна из таблиц delete restrict не ссылается на контакт с клиентом. Если это произойдет, контакт с клиентом не может быть удален.

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

Как я могу заранее определить, ссылается ли какая-либо из таблиц delete restrict на контакт с клиентом, позволяя мне скрыть операцию удаления пользовательского интерфейса, если я знаю, что это не разрешено?

Есть ли другой способ, кроме ручной проверки каждой таблицы по очереди?

1 Ответ

0 голосов
/ 02 сентября 2018

Идея - большая вещь "хвост виляет собакой". Вместо того, чтобы ваша бизнес-логика диктовала структуру БД, вы пытаетесь диктовать бизнес-логику на основе бизнес-структуры.

Но это все еще возможно, используя хранимые процедуры, например:

Сначала я создам несколько фиктивных таблиц:

create table CUSTOMER_CONTRACT (id int PRIMARY KEY );

create table CUSTOMER_CONTRACT_REF (id int PRIMARY KEY,
customer_id int REFERENCES CUSTOMER_CONTRACT(id));

Теперь к хранимой процедуре:

create or REPLACE function can_delete_contract(id int) returns boolean AS $$
BEGIN

  delete from CUSTOMER_CONTRACT c
    where c.ID = 1;

  return true;
EXCEPTION
  WHEN FOREIGN_KEY_VIOLATION then
    return false;
END;
$$ LANGUAGE plpgsql;

В случае исключения автоматически произойдет откат.

Теперь к некоторому тестированию:

select can_delete_contract(1); // true

insert into CUSTOMER_CONTRACT values (1);

select can_delete_contract(1); // true

insert into CUSTOMER_CONTRACT values (1);
insert into CUSTOMER_CONTRACT_REF values(1, 1);

select can_delete_contract(1); // false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...