创建触发器 Postgresql
Create Trigger Postgresql
我正在做一个简单的练习,给定一个任务视图我必须重新计算新插入的数据才能做到这一点我需要制作一个触发器这就是我目前所做的:
CREATE VIEW Missioni AS
SELECT d.Codice, SUM(v.Chilometri) AS KmTotali, SUM(v.Chilometri) * a.CostoKm AS CostoTotale
FROM Dipendente d join Viaggio v on v.Dipendente = d.Codice join Auto a on a.Targa = v.Auto
GROUP BY d.Codice, a.CostoKm;
CREATE OR REPLACE FUNCTION CALCULATE_MISSION()
RETURNS trigger AS $CALCULATE_MISSION$
BEGIN
DELETE FROM Missioni;
INSERT INTO Missioni SELECT Dipendente, SUM(Chilometri), SUM(Chilometri * CostoKm) FROM Viaggio v JOIN AUTO a ON a.targa = v.auto GROUP BY Dipendente;
END;
$CALCULATE_MISSION$ LANGUAGE plpgsql;
CREATE TRIGGER CalcolaVistaOneShot AFTER INSERT ON Viaggio
FOR EACH STATEMENT
EXECUTE FUNCTION CALCULATE_MISSION();
目前我正在查询编辑器中的 pgAdmin 4 上执行此操作,但出现以下错误:
ERROR: it is not possible to delete from the "missions" view
DETAIL: Views containing GROUP BY are not auto-updatable.
HINT: To allow deletions from the view, either an INSTEAD OF DELETE trigger or an ON DELETE DO INSTEAD rule without conditions must be provided.
CONTEXT: SQL statement "DELETE FROM Missions"
PL / pgSQL calculate_mission () function line 3 to SQL statement
您已将实体化视图的定义更改为标准视图。但是然后询问关于物化视图的“刷新”。所以我对你真正想要的东西感到困惑。但是,无论哪种类型视图都不能直接更新。标准视图没有dml 应用 - 它们由查询定义,每次引用视图时都是 运行。在这种情况下,根本不会触发,因为没有什么可做的。物化视图被刷新(参见文档以前引用过)与 REFRESH MATERIALIZED VIEW ddl statement. In this case your trigger consists of a single execute 语句和 return null.
create or replace function calculate_mission()
returns trigger
language plpgsql
as $$
begin
execute 'refresh materialized view missioni';
return null;
end; $$;
一些注意事项:您似乎正试图为 KmTotali 和 CostoTotale 保持“截至目前”的实时值。如果结果集很小,标准视图可能会充分执行。如果结果集很大,物化视图可能在 select 上表现更好,但涉及的表的 DML 操作必须占用整个刷新时间;当 dml activity 在基础表上很重时,问题尤其严重。此外,您仅在插入时刷新,如果我在删除或更新行的计算中更新值,会发生什么情况。我整理了一个小虚构 demo。最后,花一些时间 熟悉 Postgres 文档 。它非常完整,尽管有时可能很难准确导航到您需要的内容。
我正在做一个简单的练习,给定一个任务视图我必须重新计算新插入的数据才能做到这一点我需要制作一个触发器这就是我目前所做的:
CREATE VIEW Missioni AS
SELECT d.Codice, SUM(v.Chilometri) AS KmTotali, SUM(v.Chilometri) * a.CostoKm AS CostoTotale
FROM Dipendente d join Viaggio v on v.Dipendente = d.Codice join Auto a on a.Targa = v.Auto
GROUP BY d.Codice, a.CostoKm;
CREATE OR REPLACE FUNCTION CALCULATE_MISSION()
RETURNS trigger AS $CALCULATE_MISSION$
BEGIN
DELETE FROM Missioni;
INSERT INTO Missioni SELECT Dipendente, SUM(Chilometri), SUM(Chilometri * CostoKm) FROM Viaggio v JOIN AUTO a ON a.targa = v.auto GROUP BY Dipendente;
END;
$CALCULATE_MISSION$ LANGUAGE plpgsql;
CREATE TRIGGER CalcolaVistaOneShot AFTER INSERT ON Viaggio
FOR EACH STATEMENT
EXECUTE FUNCTION CALCULATE_MISSION();
目前我正在查询编辑器中的 pgAdmin 4 上执行此操作,但出现以下错误:
ERROR: it is not possible to delete from the "missions" view DETAIL: Views containing GROUP BY are not auto-updatable. HINT: To allow deletions from the view, either an INSTEAD OF DELETE trigger or an ON DELETE DO INSTEAD rule without conditions must be provided. CONTEXT: SQL statement "DELETE FROM Missions" PL / pgSQL calculate_mission () function line 3 to SQL statement
您已将实体化视图的定义更改为标准视图。但是然后询问关于物化视图的“刷新”。所以我对你真正想要的东西感到困惑。但是,无论哪种类型视图都不能直接更新。标准视图没有dml 应用 - 它们由查询定义,每次引用视图时都是 运行。在这种情况下,根本不会触发,因为没有什么可做的。物化视图被刷新(参见文档以前引用过)与 REFRESH MATERIALIZED VIEW ddl statement. In this case your trigger consists of a single execute 语句和 return null.
create or replace function calculate_mission()
returns trigger
language plpgsql
as $$
begin
execute 'refresh materialized view missioni';
return null;
end; $$;
一些注意事项:您似乎正试图为 KmTotali 和 CostoTotale 保持“截至目前”的实时值。如果结果集很小,标准视图可能会充分执行。如果结果集很大,物化视图可能在 select 上表现更好,但涉及的表的 DML 操作必须占用整个刷新时间;当 dml activity 在基础表上很重时,问题尤其严重。此外,您仅在插入时刷新,如果我在删除或更新行的计算中更新值,会发生什么情况。我整理了一个小虚构 demo。最后,花一些时间 熟悉 Postgres 文档 。它非常完整,尽管有时可能很难准确导航到您需要的内容。