You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL触发器报错record "new" has no field "i_produtos"如何解决

报错原因

你的触发器绑定在fabricante表上,触发器内的NEW、OLD关键字对应fabricante表触发更新时的新、旧行数据,而fabricante表本身不存在i_produtos字段,因此调用NEW.i_produtos会直接抛出字段不存在的错误。

同时你的触发逻辑也存在关联错误:你要判断当前修改的厂商是否有已销售的关联商品,需要先通过厂商ID关联到商品表,再关联销售记录,而不是直接引用商品ID。

修复方案

假设你的业务需求是如果某个厂商已经有对应商品产生了销售记录,就不允许修改该厂商的i_fabricantes字段,修正后的触发函数代码如下:

CREATE OR REPLACE FUNCTION alter_fab() RETURNS TRIGGER 
AS $alter_fab$
BEGIN
    -- 仅当i_fabricantes字段被修改时才执行校验
    IF OLD.i_fabricantes != NEW.i_fabricantes AND EXISTS(
        SELECT * FROM item i
        INNER JOIN venda ON venda.i_vendas = i.i_vendas
        -- 先关联商品表,找到属于当前修改厂商的所有商品
        INNER JOIN produtos p ON p.i_produtos = i.i_produtos
        WHERE p.i_fabricantes = OLD.i_fabricantes
    ) THEN 
        RAISE EXCEPTION 'Fabricante não pode ser alterado!';
    END IF;
    -- 行级BEFORE触发器必须返回新行数据
    RETURN NEW;
END;
$alter_fab$ LANGUAGE plpgsql;

调整说明

  • 修正了子查询的关联逻辑:通过旧的厂商IDOLD.i_fabricantes关联商品表,再关联销售记录,避免引用不存在的字段
  • 补充了必须的RETURN NEW语句,否则触发器执行完成后会抛出无返回值的错误
  • 原有触发器创建代码无需修改,可正常使用

可选场景说明

如果你的实际需求是不允许修改商品所属的厂商,当该商品已经产生销售记录,则需要把触发器绑定在produtos表上,触发函数的判断逻辑可以简化为:

IF OLD.i_fabricantes != NEW.i_fabricantes AND EXISTS(
    SELECT * FROM item i
    INNER JOIN venda ON venda.i_vendas = i.i_vendas
    WHERE i.i_produtos = NEW.i_produtos
) THEN
    RAISE EXCEPTION 'Fabricante não pode ser alterado!';
END IF;

内容的提问来源于stack exchange,提问作者Oppo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:45:08