我在PostgreSQL中有三个表:customers,services和buying_services。它是与链接表的一对多关系,因此第三个表中的外键引用前两个主键。每个表中都有一个主键。在客户表格中,我有charge
列,在服务中有tax_percents
列,在buy_services中有列quantity
,without_tax
,tax
和total
。我想写一个触发器,在quantity
列更新后更新所有without_tax
等列以及客户的charge
列。我到目前为止写了这个:
CREATE FUNCTION updateValues() RETURN TRIGGER AS
$BODY$
BEGIN
UPDATE bought_services SET
without_tax = quantity * (SELECT services.net_price FROM bought_services LEFT JOIN
services ON bought_serices.service_id = services.id),
tax = without_tax * (SELECT services.tax_percents FROM bought_services LEFT JOIN
services ON bought_serices.service_id = services.id) * 0.01,
total= without_tax + tax ;
UPDATE customers SET
charge = SELECT SUM(total) FROM bought_services LEFT JOIN customers ON
wykupione_uslugi.customer_id = customers.id WHERE bought_services.customer_id = ?
end;
$BODY$
CREATE TRIGGER UpdateBoughtServicesValues AFTER UPDATE ON bought_services
FOR EACH ROW EXECUTE PROCEDURE updateValues();
我真的不知道应该输入什么而不是?
,也就是说,我应该如何告诉postgres我想要总结我更新{{1}的所有客户服务的总金额其中一个的领域。
答案 0 :(得分:1)
与MySQL不同,Postgres有两种不同类型的触发器:一种调用每一行(作为MySQL)和语句级触发器。
在行级触发器中,可以使用记录new
直接访问更新(或插入)的行。
据我所知,你的触发器应该是这样的:
CREATE FUNCTION updatevalues() RETURN TRIGGER AS
$BODY$
declare
l_net_price decimal;
l_tax_percent decimal;
BEGIN
SELECT services.net_price, service.tax_percents
into l_net_price, l_tax_percent
FROM services
where service_id = new.service_id;
new.without_tax := quantity * l_net_price;
new.tax := without_tax * l_tax_percent;
new.total := new.without_tax + new.tax;
UPDATE customers
SET charge = (select SUM(total)
FROM bought_services
where bought_services.customer_id = new.customer_id)
where id = new.customer_id;
end;
$BODY$;
我优化了一下,只运行一次税计算的选择。
不相关,但是:触发器中的这种计算通常不是一个好主意。关系数据库设计中的黄金法则是不存储可以从现有数据派生的数据。这种聚合应该只在非常罕见的情况下进行。否则,我会在需要时简单地汇总这些数字。如果我绝对必须这样做,我只会这样做。请注意,Postgres通常比MySQL更复杂的查询要好得多(更快)。所以不要害怕加入很多桌子。只有当你看到真的给出了不可接受的性能时,才会使用这样的技巧。