根据另一个 table 的值删除行
Delete rows depending on values from another table
如何根据另一个 table 的值从我的 customer
table 中删除行,比方说 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 =
);
$body$
LANGUAGE SQL;
SELECT * FROM Customer;
我也尝试过使用 PLPGSQL 函数返回触发器,然后使用触发器来帮助删除和检查,但我迷路了。关于如何解决这个问题的任何想法?有进一步阅读的好资源吗?
你们非常亲密。我建议你使用 NOT IN
而不是 IN
:
DELETE FROM Customer
WHERE CustID = AND
CustID NOT IN (SELECT DISTINCT CustID
FROM Order
WHERE Status = 'A');
我在这里猜测 Status = 'A'
意味着 "active order"。如果是其他原因,请适当更改代码。
你的基本函数可以这样工作:
CREATE OR REPLACE FUNCTION del_cust(_custid int)
RETURNS int --③
LANGUAGE sql AS
$func$
DELETE FROM customer c
WHERE c.custid =
AND NOT EXISTS ( -- ①
SELECT FROM "order" o -- ②
WHERE o.status = 'C' -- meaning "active"?
AND o.custid =
);
RETURNING c.custid; -- ③
$func$;
① Avoid NOT IN
如果可以的话。这是低效的,而且可能是危险的。相关:
- Select rows which are not present in other table
② "order"是SQL中的一个reserved word。最好选择合法的标识符,否则您必须始终使用双引号。
③ 我把它设为RETURNS int
来表示该行是否真的被删除了。如果 DELETE
没有通过,函数 returns NULL。可选添加。
对于 触发器实现,考虑这个密切相关的答案:
- Foreign key contraints in many-to-many relationships
如何根据另一个 table 的值从我的 customer
table 中删除行,比方说 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 =
);
$body$
LANGUAGE SQL;
SELECT * FROM Customer;
我也尝试过使用 PLPGSQL 函数返回触发器,然后使用触发器来帮助删除和检查,但我迷路了。关于如何解决这个问题的任何想法?有进一步阅读的好资源吗?
你们非常亲密。我建议你使用 NOT IN
而不是 IN
:
DELETE FROM Customer
WHERE CustID = AND
CustID NOT IN (SELECT DISTINCT CustID
FROM Order
WHERE Status = 'A');
我在这里猜测 Status = 'A'
意味着 "active order"。如果是其他原因,请适当更改代码。
你的基本函数可以这样工作:
CREATE OR REPLACE FUNCTION del_cust(_custid int)
RETURNS int --③
LANGUAGE sql AS
$func$
DELETE FROM customer c
WHERE c.custid =
AND NOT EXISTS ( -- ①
SELECT FROM "order" o -- ②
WHERE o.status = 'C' -- meaning "active"?
AND o.custid =
);
RETURNING c.custid; -- ③
$func$;
① Avoid NOT IN
如果可以的话。这是低效的,而且可能是危险的。相关:
- Select rows which are not present in other table
② "order"是SQL中的一个reserved word。最好选择合法的标识符,否则您必须始终使用双引号。
③ 我把它设为RETURNS int
来表示该行是否真的被删除了。如果 DELETE
没有通过,函数 returns NULL。可选添加。
对于 触发器实现,考虑这个密切相关的答案:
- Foreign key contraints in many-to-many relationships