简体   繁体   English

PostgreSQL- Function 在表 A 上更新表 B 的 3 个共享列

[英]PostgreSQL- Function to update 3 shared columns from table B on table A

The main goal is to create a function that updates 3 columns on another table (the update of the 2 columns from the first table trigger the update on the second one).主要目标是创建一个 function 更新另一个表上的 3 列(第一个表中 2 列的更新触发第二个表的更新)。

CREATE TRIGGER                      trigger_modif_amount
AFTER INSERT OR DELETE OR UPDATE OF net_amount, iva_amount
ON                                  erp.tb_lines
FOR EACH ROW
EXECUTE PROCEDURE                   modif_amount();

The name of the 3 columns:.net_amount, iva_amount, total_amount 3列的名称:.net_amount、iva_amount、total_amount

    CREATE OR REPLACE FUNCTION modif_amount()
RETURNS TRIGGER AS $$
BEGIN
UPDATE erp.tb_invoice
SET (net_amount,iva_amount,tot_amount) = (select COALESCE(sum(net_amount),0),COALESCE(sum(iva_amount),0),COALESCE(sum(net_amount+iva_amount),0) from tb_lines where invoice_id = coalesce(NEW.invoice_id, OLD.invoice_id))
WHERE invoice_id = coalesce(NEW.invoice_id, OLD.invoice_id);
END; 
$$ LANGUAGE plpsql;

The tables:表格:

  CREATE TABLE erp.tb_invoice (
    co_code            CHARACTER(3) NOT NULL,
    invoice_id         INT NOT NULL,
    invoice_no         CHARACTER VARYING(15)  NOT NULL,
    cust_no            CHARACTER(5) NOT NULL,
    site_id            INT NOT NULL,
    payed              CHARACTER(1) NOT NULL DEFAULT 'N',
    net_amount         REAL NOT NULL,
    iva_amount         REAL NOT NULL,
    tot_amount         REAL NOT NULL,
    last_updated_by    CHARACTER VARYING(20) DEFAULT 'SYSTEM',
    last_update_date   DATE NOT NULL,
    CONSTRAINT pk_invoice PRIMARY KEY (invoice_id),
    CONSTRAINT fk_invoice_company FOREIGN KEY (co_code) REFERENCES erp.tb_company (co_code),
    CONSTRAINT fk_invoice_customer FOREIGN KEY (cust_no) REFERENCES erp.tb_customer (cust_no),
    CONSTRAINT fk_invoice_site FOREIGN KEY (site_id) REFERENCES erp.tb_site (site_id)  
  );
  

  CREATE TABLE erp.tb_lines (
    invoice_id            INT NOT NULL,
    line_id               INT  NOT NULL,
    line_num              INT NOT NULL,
    item                  CHARACTER(5),
    description           CHARACTER VARYING(120)  NOT NULL,
    net_amount            REAL NOT NULL,
    iva_amount            REAL NOT NULL,
    last_updated_by       CHARACTER VARYING(20) DEFAULT 'SYSTEM',
    last_update_date      DATE NOT NULL,
    CONSTRAINT pk_lines PRIMARY KEY (line_id),
    CONSTRAINT fk_lines_invoice FOREIGN KEY (invoice_id) REFERENCES erp.tb_invoice (invoice_id)
  );

This trigger definition to only execute the function (modif_amount) if column .net_amount) and (iva_amount) is specified as a target in the UPDATE command:此触发器定义仅执行 function (modif_amount) 如果列 .net_amount) 和 (iva_amount) 被指定为 UPDATE 命令中的目标:

CREATE TRIGGER                trigger_modif_amount
AFTER UPDATE OF net_amount,iva_amount ON tb_lines
FOR EACH ROW
EXECUTE PROCEDURE             modif_amount();

This form only executes the function (modif_amount) if column .net_amount), (iva_amount) has in fact changed value:如果列 .net_amount), (iva_amount) 实际上改变了值,则此表单仅执行 function (modif_amount):

CREATE TRIGGER                trigger_modif_amount
AFTER UPDATE
ON                            tb_lines
FOR EACH ROW
 WHEN ((OLD.net_amount IS DISTINCT FROM NEW.net_amount) AND 
       (OLD.iva_amount IS DISTINCT FROM NEW.iva_amount) )
EXECUTE PROCEDURE             modif_amount();

You can create trigger which trigger after update of specific fields您可以创建在更新特定字段后触发的触发器

https://www.postgresql.org/docs/14/sql-createtrigger.html https://www.postgresql.org/docs/14/sql-createtrigger.html

CREATE TRIGGER test
    AFTER INSERT OR DELETE OR UPDATE OF net_amount, iva_amount
    ON tb_lines
    FOR EACH ROW
    EXECUTE PROCEDURE modif_amount();

Updating overal sum in another table inside trigger is not a good idea (it moves business logic into triggers and is not save).在触发器内的另一个表中更新总和不是一个好主意(它将业务逻辑移动到触发器中并且不保存)。

Version 1版本 1

update tb_invoice set
(net_amount,iva_amount,tot_amount) = (select COALESCE(sum(net_amount),0),COALESCE(sum(iva_amount),0),COALESCE(sum(net_amount+iva_amount),0) from tb_lines where invoice_id = coalesce(NEW.invoice_id, OLD.invoice_id))
where invoice_id = coalesce(NEW.invoice_id, OLD.invoice_id);

Version 2版本 2

update tb_invoice set
(net_amount,iva_amount,tot_amount) = (select COALESCE(sum(net_amount),0),COALESCE(sum(iva_amount),0),COALESCE(sum(net_amount+iva_amount),0) from tb_lines where tb_lines.invoice_id = tb_invoice.invoice_id)
where invoice_id = coalesce(NEW.invoice_id, OLD.invoice_id);

COALESCE in sum is needed to ensure, that even if invoice has no positions sums will be calculated as 0.总和需要 COALESCE 来确保,即使发票没有头寸,总和也将计算为 0。

COALESCE in where is needed because during insert operation there is no OLD.invoice_id, and during delete operation there is no NEW.invoice_id.需要合并的地方,因为在插入操作期间没有 OLD.invoice_id,在删除操作期间没有 NEW.invoice_id。

My assumption is, that invoice_id cannot be changed.我的假设是,invoice_id 无法更改。 If not, that moving a position from one invoice to another should update ole and new one.如果不是,将 position 从一张发票移动到另一张发票应该更新 ole 和新发票。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM