PostgreSQL计数触发器疑问:模式指定与TG_TABLE_NAME识别问题
问题解答
疑问1:设置search_path后触发器函数仍需指定表模式
触发器函数的search_path是创建函数时固化的,不会继承调用时会话的search_path配置。哪怕你后续修改了会话的search_path,函数内部的路径规则还是创建时的设置。
解决方法:
- 创建触发器函数时,显式指定
search_path并包含目标模式:
CREATE OR REPLACE FUNCTION update_nb_transf() RETURNS TRIGGER SET search_path = dsfv, public AS $$ BEGIN -- 此处无需加dsfv.前缀,直接写表名即可 UPDATE poste_hta_bt SET nb_transf = (SELECT COUNT(*) FROM transfo_hta_bt WHERE code_pt = NEW.code_pt) WHERE code_pt = NEW.code_pt; RETURN NEW; END; $$ LANGUAGE plpgsql;
- 或者创建函数前先将当前会话的
search_path设为包含dsfv,再执行函数创建语句,函数会自动继承该路径配置。
疑问2:用TG_TABLE_NAME替代dsfv.transfo_hta_bt时变量不被识别
TG_TABLE_NAME仅返回不带模式的表名,而且静态SQL无法直接用变量替换表名这类标识符,必须通过**动态SQL(EXECUTE)**拼接执行逻辑。
结合TG_TABLE_SCHEMA(获取触发器所在表的模式)的示例:
CREATE OR REPLACE FUNCTION update_nb_transf() RETURNS TRIGGER SET search_path = dsfv, public AS $$ DECLARE v_full_table_name TEXT := TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME; BEGIN EXECUTE format( 'UPDATE poste_hta_bt SET nb_transf = (SELECT COUNT(*) FROM %I WHERE code_pt = $1) WHERE code_pt = $1', v_full_table_name ) USING NEW.code_pt; RETURN NEW; END; $$ LANGUAGE plpgsql;
这里用format()的%I处理标识符避免SQL注入,USING传递参数,比直接拼接字符串更安全可靠。
内容的提问来源于stack exchange,提问作者ennine
相关产品推荐
相关产品推荐

