You need to enable JavaScript to run this app. PostgreSQL创建触发器提示函数不存在但\df可查的问题求助
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL创建触发器提示函数不存在但\df可查的问题求助

问题核心原因

你写的创建触发器的SQL里有两处语法错误,导致函数签名匹配失败:

  1. 触发器函数参数的引号用错
    PostgreSQL中双引号"用于引用标识符(表名、列名、函数名等),单引号'才用于包裹字符串常量。你传递给public.audit_logger的审计表名参数用了双引号包裹,PostgreSQL会把它解析为字段名/标识符,而不是字符串参数,因此会报错找不到对应签名的public.audit_logger()函数。
  2. 触发器函数的参数逻辑不符合要求
    PostgreSQL的触发器函数不能定义显式入参,所有传入的参数都是通过特殊变量TG_ARGV数组在函数内部获取的,如果你定义audit_logger的时候主动写了入参,也会导致签名不匹配。

修复方案

第一步:修改prepare_audit函数中触发器创建的format语句

把原来的双引号替换为单引号,注意因为你在format字符串里要输出单引号,需要用两个单引号转义:

CREATE OR REPLACE FUNCTION prepare_audit() RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
DO
$$
DECLARE
_sql text;
BEGIN
FOR _sql IN
SELECT format('CREATE TABLE IF NOT EXISTS audit.%I_%I(timestamp timestamptz NOT NULL, entity jsonb NOT NULL)'
, schemaname
, tablename)
FROM   pg_catalog.pg_tables
WHERE  schemaname = 'public'
LOOP
EXECUTE _sql;
END LOOP;
END
$$;
DO
$$
DECLARE
_sql text;
BEGIN
FOR _sql IN
SELECT format('DROP TRIGGER IF EXISTS audittrigger on %I.%I; CREATE TRIGGER audittrigger AFTER INSERT ON %I.%I FOR EACH ROW EXECUTE PROCEDURE public.audit_logger(''audit.%I_%I'')'
, schemaname
, tablename
, schemaname
, tablename
, schemaname
, tablename)
FROM   pg_catalog.pg_tables
WHERE  schemaname = 'public'
LOOP
EXECUTE _sql;
END LOOP;
END
$$;
END
$func$;

第二步:确认audit_logger函数的定义符合触发器函数要求

触发器函数必须定义为返回trigger类型,且不能声明显式入参,正确的定义结构示例如下:

CREATE OR REPLACE FUNCTION public.audit_logger() 
RETURNS trigger 
LANGUAGE plpgsql
AS $$
DECLARE
  audit_table_name text := TG_ARGV[0]; -- 取传入的第一个参数,即审计表名
BEGIN
  -- 此处写你的审计日志插入逻辑,示例如下:
  EXECUTE format('INSERT INTO %I (timestamp, entity) VALUES (now(), $1)', audit_table_name) USING to_jsonb(NEW);
  RETURN NEW;
END;
$$;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 17:30:00