Postgresql 在插入值后使用触发器更新列值
Postgresql using Trigger to update column values after inserting values
我想将值插入表 A,然后更新列[amount_hkd]。
我已经成功使用了触发器,但是性能真的很慢,应用触发器后需要一个小时才能完成 8400 行的插入。
我怎样才能提高性能?
感谢您的帮助
要执行的语句:
INSERT INTO tableA (suppliers, invoice_dates, shipment_dates, amounts, currency, currency_conversion_rate)
SELECT l.supplier, l.invoice_date, l.shipment_date, l.amount, l.currency, o.currency_conversion_rate
FROM tableB l
LEFT JOIN tableC o
ON l.currency = o.currency_code
WHERE l.supplier = 'ABC'
我创建的函数:
CREATE OR REPLACE FUNCTION cal()
RETURNS TRIGGER AS $$
BEGIN
UPDATE tableA
SET amount_hkd = NEW.amounts * NEW.currency_conversion_rate;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
我尝试的第一个触发器:
CREATE CONSTRAINT TRIGGER update_amount
AFTER INSERT ON tableA
DEFERRABLE
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE cal();
我试过的第二个触发器:
CREATE TRIGGER update_amount
AFTER INSERT ON tableA
FOR EACH ROW
EXECUTE PROCEDURE cal();
插入后更新行的效率非常低。更好的方法是使用 BEFORE
触发器,它可以在插入 之前 修改新行:
CREATE OR REPLACE FUNCTION cal() RETURNS trigger
LANGUAGE plpgsql AS
$$BEGIN
NEW.amount_hkd := NEW.amounts * NEW.currency_conversion_rate;
RETURN NEW;
END;$$;
CREATE TRIGGER update_amount
BEGORE INSERT ON tableA FOR EACH ROW
EXECUTE PROCEDURE cal();
您没有指定您的 Postgres 版本,但如果至少是 V12,您就可以完全避免触发器。将列 amount_hkd
定义为生成的列。您不仅避免了触发器,而且还消除了更新 currency_conversion_rate
and/or amount
和忘记更新 amount_hkd
或直接更新到 [=11] 的维护问题=].类似于:(参见 example here)
create table table_a( a_id integer generated always as identity
, amounts decimal
, currency_conversion_rate decimal
, amount_hkd decimal generated always as ( amounts * currency_conversion_rate ) stored
);
我想将值插入表 A,然后更新列[amount_hkd]。 我已经成功使用了触发器,但是性能真的很慢,应用触发器后需要一个小时才能完成 8400 行的插入。 我怎样才能提高性能? 感谢您的帮助
要执行的语句:
INSERT INTO tableA (suppliers, invoice_dates, shipment_dates, amounts, currency, currency_conversion_rate)
SELECT l.supplier, l.invoice_date, l.shipment_date, l.amount, l.currency, o.currency_conversion_rate
FROM tableB l
LEFT JOIN tableC o
ON l.currency = o.currency_code
WHERE l.supplier = 'ABC'
我创建的函数:
CREATE OR REPLACE FUNCTION cal()
RETURNS TRIGGER AS $$
BEGIN
UPDATE tableA
SET amount_hkd = NEW.amounts * NEW.currency_conversion_rate;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
我尝试的第一个触发器:
CREATE CONSTRAINT TRIGGER update_amount
AFTER INSERT ON tableA
DEFERRABLE
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE cal();
我试过的第二个触发器:
CREATE TRIGGER update_amount
AFTER INSERT ON tableA
FOR EACH ROW
EXECUTE PROCEDURE cal();
插入后更新行的效率非常低。更好的方法是使用 BEFORE
触发器,它可以在插入 之前 修改新行:
CREATE OR REPLACE FUNCTION cal() RETURNS trigger
LANGUAGE plpgsql AS
$$BEGIN
NEW.amount_hkd := NEW.amounts * NEW.currency_conversion_rate;
RETURN NEW;
END;$$;
CREATE TRIGGER update_amount
BEGORE INSERT ON tableA FOR EACH ROW
EXECUTE PROCEDURE cal();
您没有指定您的 Postgres 版本,但如果至少是 V12,您就可以完全避免触发器。将列 amount_hkd
定义为生成的列。您不仅避免了触发器,而且还消除了更新 currency_conversion_rate
and/or amount
和忘记更新 amount_hkd
或直接更新到 [=11] 的维护问题=].类似于:(参见 example here)
create table table_a( a_id integer generated always as identity
, amounts decimal
, currency_conversion_rate decimal
, amount_hkd decimal generated always as ( amounts * currency_conversion_rate ) stored
);