Удалять строки в зависимости от значений из другой таблицы - PullRequest
1 голос
/ 26 мая 2020

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

Если у клиента нет активных заказов, они должны быть удалены из БД вместе со своими строками (выполняется с использованием CASCADE). Однако, если у них вообще есть активные ордера, их нельзя удалить.

Я думал о функции PLPG SQL, а затем использовал ее в триггере для проверки, но я потерялся. У меня есть базовый c блок из SQL, показанный ниже, моей первой идеи по удалению записи соответственно. Но он не работает должным образом, поскольку он удаляет клиента независимо от статуса, для этой функции нужен только один отмененный заказ, а не все отмененные.

CREATE OR REPLACE FUNCTION DelCust(int)
RETURNS void AS $body$
    DELETE FROM Customer 
      WHERE CustID IN (
      SELECT CustID
      FROM Order
      WHERE Status = 'C'
      AND CustID = $1
    );
$body$
LANGUAGE SQL;

SELECT * FROM Customer;

Я также пробовал использовать PLPG SQL функция возвращает триггер, а затем использует триггер, чтобы помочь с удалением и проверками, но я потерялся в этом. Есть мысли, как это исправить? Есть ли хорошие источники для дальнейшего чтения?

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Ваша основная c функция может работать следующим образом:

CREATE OR REPLACE FUNCTION del_cust(_custid int)
  RETURNS int  --③
  LANGUAGE sql AS
$func$
DELETE FROM customer c
WHERE  c.custid = $1
AND    NOT EXISTS ( -- ①
   SELECT FROM "order" o  -- ②
   WHERE  o.status = 'C'  -- meaning "active"?
   AND    o.custid = $1
   );
RETURNING c.custid; -- ③
$func$;

Избегайте NOT IN, если можете. Это неэффективно и потенциально опасно. Связано:

② «порядок» - это зарезервированное слово в SQL. Лучше выбрать допустимый идентификатор, иначе вам придется всегда заключать в двойные кавычки.

③ Я сделал RETURNS int, чтобы указать, действительно ли строка была удалена. Функция возвращает NULL, если DELETE не проходит через go. Необязательное добавление.


Для реализации триггера рассмотрите этот тесно связанный ответ:

0 голосов
/ 26 мая 2020

Вы были очень близки. Я предлагаю вам использовать NOT IN вместо IN:

DELETE FROM Customer 
  WHERE CustID = $1 AND
        CustID NOT IN (SELECT DISTINCT CustID
                         FROM Order
                         WHERE Status = 'A');

Я предполагаю, что Status = 'A' означает «активный заказ». Если это что-то еще, измените код соответствующим образом.

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