PostgreSQL库存校验触发器触发无限循环栈溢出问题咨询
问题根因
- 触发无限递归的直接原因:你在绑定了warehouse表UPDATE事件的触发器内部,再次执行了
UPDATE warehouse语句,这个更新操作会再次触发同一个触发器,无限递归调用最终超出栈深度限制,触发栈溢出报错。 - 实现逻辑错误:BEFORE UPDATE行级触发器不需要手动编写SQL修改原表数据,校验通过后直接返回
NEW记录,数据库会自动用NEW的字段值完成行更新;如果校验不通过直接抛出错误即可终止更新操作。 - 冗余查询问题:你代码中查询warehouse表拿到的
print.quantity和触发器内置的OLD.quantity(更新前的库存值)完全一致,额外关联drugstore表也没有用到任何该表的字段,属于完全冗余的逻辑。 - 你的更新语句本身存在语法错误,
warehouseset中间缺少空格,正确写法为update warehouse set quantity=2 where iddrug=1 AND iddrugstore=2;
正确实现代码
你需要的「更新后库存低于0则阻止更新」功能可以直接简化为以下逻辑:
-- 创建校验库存的触发器函数 CREATE OR REPLACE FUNCTION check_warehouse_quantity() RETURNS TRIGGER LANGUAGE PLPGSQL AS $$ BEGIN -- 校验更新后的库存值是否小于0 IF NEW.quantity < 0 THEN -- 抛出错误终止更新 RAISE EXCEPTION '药品ID: % 在门店ID: % 的库存不能为负数', NEW.iddrug, NEW.iddrugstore; END IF; -- 校验通过返回NEW即可,数据库会自动完成更新 RETURN NEW; END; $$; -- 先删除原有错误触发器 DROP TRIGGER IF EXISTS triggerBuyArticle ON warehouse; -- 创建新的触发器,仅在quantity字段更新时触发 CREATE TRIGGER trigger_check_quantity_before_update BEFORE UPDATE OF quantity ON warehouse FOR EACH ROW EXECUTE FUNCTION check_warehouse_quantity();
注意事项
如果你的业务场景是处理出库扣减库存,建议在出库单据表上编写触发器修改仓库库存,不要在仓库表的触发器中再次修改仓库表,从根源避免递归触发的问题。
内容的提问来源于stack exchange,提问作者user13350952
相关产品推荐
相关产品推荐

