如何找出postgresql中更新的行

时间:2017-06-14 17:28:50

标签: postgresql triggers

我在PostgreSQL中有三个表:customers,services和buying_services。它是与链接表的一对多关系,因此第三个表中的外键引用前两个主键。每个表中都有一个主键。在客户表格中,我有charge列,在服务中有tax_percents列,在buy_services中有列quantitywithout_taxtaxtotal 。我想写一个触发器,在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}的所有客户服务的总金额其中一个的领域。

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更复杂的查询要好得多(更快)。所以不要害怕加入很多桌子。只有当你看到真的给出了不可接受的性能时,才会使用这样的技巧。