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

如何编写PostgreSQL触发器函数阻止删除关联供应商记录

问题背景

我有两张表:

CREATE TABLE public.t_products
(
    product_id integer NOT NULL,
    product_name character varying(100) COLLATE pg_catalog."default" NOT NULL,
    supplier_id integer NOT NULL,
    CONSTRAINT t_products_pkey PRIMARY KEY (product_id)
);   

CREATE TABLE public.t_suppliers
(
    supplier_id integer NOT NULL,
    supplier_name character varying(100) NOT NULL,
    CONSTRAINT t_suppliers_pkey PRIMARY KEY (supplier_id)
);

我希望编写一个函数,当t_suppliers中的供应商ID在t_products表中被引用时,禁止删除该供应商记录。我知道可以通过外键实现此功能,但想学习如何编写自定义函数,请问该函数的函数体应如何编写?

已定义触发器如下:

CREATE TRIGGER deleting_supplier
   BEFORE DELETE ON t_suppliers FOR EACH ROW
   EXECUTE PROCEDURE is_del_possible();

函数框架如下:

CREATE OR REPLACE FUNCTION is_del_possible() RETURNS trigger AS
$$BEGIN
   ???
END;$$ LANGUAGE plpgsql;

自定义触发器函数实现

你可以通过查询t_products表检查当前待删除的供应商是否存在关联记录,若存在则抛出异常阻止删除。完整函数体如下:

CREATE OR REPLACE FUNCTION is_del_possible() RETURNS trigger AS
$$BEGIN
    -- 检查待删除供应商是否被产品表引用
    IF EXISTS (
        SELECT 1 
        FROM public.t_products 
        WHERE supplier_id = OLD.supplier_id
    ) THEN
        -- 抛出异常中断删除,给出明确提示
        RAISE EXCEPTION '供应商ID % 仍有产品关联,无法删除', OLD.supplier_id;
    END IF;
    -- 无关联则返回OLD,允许执行删除
    RETURN OLD;
END;$$ LANGUAGE plpgsql;

逻辑说明

  • OLD.supplier_id:在BEFORE DELETE触发器中,OLD代表即将被删除的记录行,通过它可获取目标供应商ID。
  • EXISTS子查询:高效判断t_products中是否存在使用该供应商ID的记录,只要有匹配行就返回true。
  • RAISE EXCEPTION:检测到关联记录时,抛出异常终止删除操作,同时返回自定义错误提示。
  • RETURN OLD:未检测到关联时,返回OLD表示允许执行后续删除流程(BEFORE DELETE触发器要求必须返回OLD或NULL,返回NULL会取消删除)。

测试验证

尝试删除有产品关联的供应商时,会收到如下错误提示:

ERROR:  供应商ID 1 仍有产品关联,无法删除
CONTEXT:  PL/pgSQL function is_del_possible() line 6 at RAISE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:22:14