根据另一个表的值删除行

问题描述 投票:0回答:1

如何删除我的行 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函数返回一个触发器,然后用触发器来帮助删除和检查,但是我对这个问题很迷茫。有什么想法可以解决这个问题吗?有什么好的来源可以进一步阅读吗?

sql database postgresql plpgsql pgadmin-4
1个回答
0
投票

你很接近了。我建议你使用 NOT IN 而不是 IN:

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

我猜想 Status = 'A' 意思是 "活动订单"。如果是其他的东西,就适当的修改代码。


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

避免 NOT IN 如果你能。效率低下,而且有可能会有奸情。相关的。

②"令 "是 保留字 在SQL中。最好选择一个合法的标识符,否则就得一直用双引号。

③我把它做成了 RETURNS int 来表示该行是否真的被删除。如果该行被删除,函数返回NULL。DELETE 不通过。可选添加。


对于一个 触发执行,考虑这个密切相关的答案。

© www.soinside.com 2019 - 2024. All rights reserved.