insert/update/delete触发器如何使用相同的触发器函数避免新旧对象的问题
How to use the same trigger function for insert/update/delete triggers avoiding the problem with new and old objects
我正在寻找解决这种情况的优雅方法:
- 我创建了一个触发器函数,每当在
warehouse_supplies
.[=35= 上插入或更新行时,它会使用一些详细信息行的总和来更新 table supply
]
- PostgreSQL
insert or update
语法允许我为插入和更新条件共享相同的函数 sync_supply_stock()
。
- 然而,当我尝试将
after delete
条件连接到函数时,它不能被重用(尽管它在逻辑上是有效的),因为返回的对象必须是 old
而不是 new
.
-- The function I want to use for the 3 conditions (insert, update, delete)
create or replace function sync_supply_stock ()
returns trigger
as $$
begin
-- update the supply whose stock just changed in warehouse_supply with
-- the sum its stocks on all the warehouses.
update supply
set stock = (select sum(stock) from warehouse_supplies where supply_id = new.supply_id)
where supply_id = new.supply_id;
return new;
end;
$$ language plpgsql;
-- The (probably) unnecessary copy of the previous function, this time returning old.
create or replace function sync_supply_stock2 ()
returns trigger
as $$
begin
-- update the supply whose stock just changed in warehouse_supply with
-- the sum its stocks on all the warehouses.
update supply
set stock = (select sum(stock) from warehouse_supplies where supply_id = old.supply_id)
where supply_id = old.supply_id;
return old;
end;
$$ language plpgsql;
-- The after insert/update trigger
create trigger on_warehouse_supplies__after_upsert after insert or update
on warehouse_supplies for each row
execute procedure sync_supply_stock ();
-- The after delete trigger
create trigger on_warehouse_supplies__after_delete after delete
on warehouse_supplies for each row
execute procedure sync_supply_stock2 ();
我是不是遗漏了什么或者是否有任何修复方法可以将 sync_supply_stock2()
复制为 sync_supply_stock2()
?
编辑
为了未来读者的利益,根据@bergi 的回答和讨论,这是一个可能的分解解决方案
create or replace function sync_supply_stock ()
returns trigger
as $$
declare
_supply_id int;
begin
-- read the supply_id column from `new` on insert/update conditions and from `old` on delete conditions
_supply_id = coalesce(new.supply_id, old.supply_id);
-- update the supply whose stock just changed in of_warehouse_supply with
-- the sum its stocks on all the warehouses.
update of_supply
set stock = (select sum(stock) from of_warehouse_supplies where supply_id = _supply_id)
where supply_id = _supply_id;
-- returns `new` on insert/update conditions and `old` on delete conditions
return coalesce(new, old);
end;
$$ language plpgsql;
create trigger on_warehouse_supplies__after_upsert after insert or update
on of_warehouse_supplies for each row
execute procedure sync_supply_stock ();
create trigger on_warehouse_supplies__after_delete after delete
on of_warehouse_supplies for each row
execute procedure sync_supply_stock ();
for the returning object must be old
instead of new
.
没有。 return 值仅与 BEFORE ROW
或 INSTEAD OF
触发器相关。来自 the docs:“触发 row-level 触发器的 return 值 AFTER
或触发 statement-level 触发器 BEFORE
或 AFTER
总是被忽略;它也可能是 null".
因此您只需创建 sync_supply_stock
触发器函数 RETURN NULL
即可用于所有操作。
我正在寻找解决这种情况的优雅方法:
- 我创建了一个触发器函数,每当在
warehouse_supplies
.[=35= 上插入或更新行时,它会使用一些详细信息行的总和来更新 tablesupply
] - PostgreSQL
insert or update
语法允许我为插入和更新条件共享相同的函数sync_supply_stock()
。 - 然而,当我尝试将
after delete
条件连接到函数时,它不能被重用(尽管它在逻辑上是有效的),因为返回的对象必须是old
而不是new
.
-- The function I want to use for the 3 conditions (insert, update, delete)
create or replace function sync_supply_stock ()
returns trigger
as $$
begin
-- update the supply whose stock just changed in warehouse_supply with
-- the sum its stocks on all the warehouses.
update supply
set stock = (select sum(stock) from warehouse_supplies where supply_id = new.supply_id)
where supply_id = new.supply_id;
return new;
end;
$$ language plpgsql;
-- The (probably) unnecessary copy of the previous function, this time returning old.
create or replace function sync_supply_stock2 ()
returns trigger
as $$
begin
-- update the supply whose stock just changed in warehouse_supply with
-- the sum its stocks on all the warehouses.
update supply
set stock = (select sum(stock) from warehouse_supplies where supply_id = old.supply_id)
where supply_id = old.supply_id;
return old;
end;
$$ language plpgsql;
-- The after insert/update trigger
create trigger on_warehouse_supplies__after_upsert after insert or update
on warehouse_supplies for each row
execute procedure sync_supply_stock ();
-- The after delete trigger
create trigger on_warehouse_supplies__after_delete after delete
on warehouse_supplies for each row
execute procedure sync_supply_stock2 ();
我是不是遗漏了什么或者是否有任何修复方法可以将 sync_supply_stock2()
复制为 sync_supply_stock2()
?
编辑
为了未来读者的利益,根据@bergi 的回答和讨论,这是一个可能的分解解决方案
create or replace function sync_supply_stock ()
returns trigger
as $$
declare
_supply_id int;
begin
-- read the supply_id column from `new` on insert/update conditions and from `old` on delete conditions
_supply_id = coalesce(new.supply_id, old.supply_id);
-- update the supply whose stock just changed in of_warehouse_supply with
-- the sum its stocks on all the warehouses.
update of_supply
set stock = (select sum(stock) from of_warehouse_supplies where supply_id = _supply_id)
where supply_id = _supply_id;
-- returns `new` on insert/update conditions and `old` on delete conditions
return coalesce(new, old);
end;
$$ language plpgsql;
create trigger on_warehouse_supplies__after_upsert after insert or update
on of_warehouse_supplies for each row
execute procedure sync_supply_stock ();
create trigger on_warehouse_supplies__after_delete after delete
on of_warehouse_supplies for each row
execute procedure sync_supply_stock ();
for the returning object must be
old
instead ofnew
.
没有。 return 值仅与 BEFORE ROW
或 INSTEAD OF
触发器相关。来自 the docs:“触发 row-level 触发器的 return 值 AFTER
或触发 statement-level 触发器 BEFORE
或 AFTER
总是被忽略;它也可能是 null".
因此您只需创建 sync_supply_stock
触发器函数 RETURN NULL
即可用于所有操作。