根据另一个表中的值删除行

时间:2020-05-26 15:50:00

标签: sql postgresql plpgsql sql-delete

如何根据另一个表(例如,customer)中的值从我的orders表中删除行?

如果客户没有有效的订单,则应该能够将其及其行(使用CASCADE完成)从数据库中删除。但是,如果他们有任何有效的订单,就无法删除它们。

我考虑过PLPGSQL函数,然后在触发器中使用它进行检查,但我迷路了。我有下面所示的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;

我还尝试过使用PLPGSQL函数返回触发器,然后使用触发器来帮助进行删除和检查,但是我迷失了。有关如何解决此问题的任何想法?有什么好的资料可供进一步阅读吗?

2 个答案:

答案 0 :(得分:0)

您非常亲密。我建议您使用NOT IN而不是IN

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

我在这里猜测Status = 'A'的意思是“有效订单”。如果还有其他问题,请适当更改代码。

答案 1 :(得分:0)

您的基本功能可以这样工作:

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$;

Avoid NOT IN(如果可以)。这是低效率的,并且可能是危险的。相关:

②“ order”在SQL中是reserved word。最好选择一个合法的标识符,否则您必须始终加双引号。

③我使RETURNS int表示该行是否实际上已删除。如果DELETE没有通过,该函数将返回NULL。可选添加。


对于触发实施,请考虑以下密切相关的答案: