如何在 Postgres 中触发更新后
How to trigger AFTER UPDATE in Postgres
我正在尝试 运行 当 table 更新时 procedure/function (insert/delete/update),但是,该函数似乎没有得到 运行 当触发器发生或触发器未在插入时被触发。
函数和触发器:
CREATE OR REPLACE FUNCTION fn_rental_trigger() RETURNS TRIGGER AS $$
BEGIN
CALL get_top_ten_rentals();
RETURN NULL;
END; $$
LANGUAGE plpgsql;
CREATE TRIGGER tr_new_rentals
AFTER UPDATE ON public.rental
EXECUTE FUNCTION public.fn_rental_trigger();
插入调用:
INSERT INTO public.rental (rental_date, inventory_id, customer_id, return_date, staff_id, last_update)
VALUES (NOW(), 4030, 459, NOW() + interval '7 day', 1, NOW());
存储过程按预期工作,当我 运行 它单独运行时,我得到了我想要的。 运行 我尝试的每一种方法都失败了,那么 运行 一个在 table 更新上执行工作程序的触发器的正确方法是什么?
对于上下文,这是基于来自 postgres tutorial website 的 dvd 租赁数据库。
编辑
存储过程:
CREATE OR REPLACE PROCEDURE get_top_ten_rentals()
AS
$$
-- Start a tansaction to get the data
BEGIN
-- clear out existing data to refresh list
DELETE FROM report.top_ten_rentals;
INSERT INTO report.top_ten_rentals (title, inventory_id, rating, length, times_rented, total)
SELECT f.title AS title,
r.inventory_id AS inventory_id,
f.rating,
fn_transform_length(f.length),
COUNT(*) AS times_rented,
SUM(p.amount) AS total
FROM public.payment AS p
JOIN public.rental AS r ON p.rental_id = r.rental_id
JOIN public.inventory AS i ON r.inventory_id = i.inventory_id
JOIN public.film AS f ON i.film_id = f.film_id
GROUP BY r.inventory_id, f.title, f.rating, f.length
ORDER BY total DESC
LIMIT 10;
-- Rollback when there is an exception to preserve data integrity
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
$$
LANGUAGE plpgsql;
回答 Adrian Klaver 的其他问题:
- 是的,这是有意为之,但可以改变。
- 因为这是一项要求,一个愚蠢的要求,但仍然是必需的。
我也尝试过 运行 触发器:
CREATE TRIGGER tr_new_rentals
AFTER UPDATE ON public.rental
FOR EACH ROW
EXECUTE FUNCTION public.fn_rental_trigger();
如果需要每行 运行ning,但是,这也不会执行该过程,因此我尝试更新的 table 永远不会收到任何数据。
要触发所有数据更改事件的触发器,请将 事件 编码为 INSERT OR UPDATE OR DELETE
:
CREATE TRIGGER tr_new_rentals
AFTER INSERT OR UPDATE OR DELETE ON public.rental
FOR EACH ROW
EXECUTE FUNCTION public.fn_rental_trigger()
由于前10条数据只依赖于表中的数据,而不是导致数据变化的事件(插入、更新或删除),所以触发器可以安全地定义为所有数据变化事件的一个触发器。
我正在尝试 运行 当 table 更新时 procedure/function (insert/delete/update),但是,该函数似乎没有得到 运行 当触发器发生或触发器未在插入时被触发。
函数和触发器:
CREATE OR REPLACE FUNCTION fn_rental_trigger() RETURNS TRIGGER AS $$
BEGIN
CALL get_top_ten_rentals();
RETURN NULL;
END; $$
LANGUAGE plpgsql;
CREATE TRIGGER tr_new_rentals
AFTER UPDATE ON public.rental
EXECUTE FUNCTION public.fn_rental_trigger();
插入调用:
INSERT INTO public.rental (rental_date, inventory_id, customer_id, return_date, staff_id, last_update)
VALUES (NOW(), 4030, 459, NOW() + interval '7 day', 1, NOW());
存储过程按预期工作,当我 运行 它单独运行时,我得到了我想要的。 运行 我尝试的每一种方法都失败了,那么 运行 一个在 table 更新上执行工作程序的触发器的正确方法是什么?
对于上下文,这是基于来自 postgres tutorial website 的 dvd 租赁数据库。
编辑
存储过程:
CREATE OR REPLACE PROCEDURE get_top_ten_rentals()
AS
$$
-- Start a tansaction to get the data
BEGIN
-- clear out existing data to refresh list
DELETE FROM report.top_ten_rentals;
INSERT INTO report.top_ten_rentals (title, inventory_id, rating, length, times_rented, total)
SELECT f.title AS title,
r.inventory_id AS inventory_id,
f.rating,
fn_transform_length(f.length),
COUNT(*) AS times_rented,
SUM(p.amount) AS total
FROM public.payment AS p
JOIN public.rental AS r ON p.rental_id = r.rental_id
JOIN public.inventory AS i ON r.inventory_id = i.inventory_id
JOIN public.film AS f ON i.film_id = f.film_id
GROUP BY r.inventory_id, f.title, f.rating, f.length
ORDER BY total DESC
LIMIT 10;
-- Rollback when there is an exception to preserve data integrity
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
$$
LANGUAGE plpgsql;
回答 Adrian Klaver 的其他问题:
- 是的,这是有意为之,但可以改变。
- 因为这是一项要求,一个愚蠢的要求,但仍然是必需的。
我也尝试过 运行 触发器:
CREATE TRIGGER tr_new_rentals
AFTER UPDATE ON public.rental
FOR EACH ROW
EXECUTE FUNCTION public.fn_rental_trigger();
如果需要每行 运行ning,但是,这也不会执行该过程,因此我尝试更新的 table 永远不会收到任何数据。
要触发所有数据更改事件的触发器,请将 事件 编码为 INSERT OR UPDATE OR DELETE
:
CREATE TRIGGER tr_new_rentals
AFTER INSERT OR UPDATE OR DELETE ON public.rental
FOR EACH ROW
EXECUTE FUNCTION public.fn_rental_trigger()
由于前10条数据只依赖于表中的数据,而不是导致数据变化的事件(插入、更新或删除),所以触发器可以安全地定义为所有数据变化事件的一个触发器。