CREATE OR REPLACE FUNCTION cdc_TABLENAME_function() RETURNS trigger AS $cdc_function$ DECLARE op cdc_operation_enum; BEGIN op = TG_OP; IF (TG_WHEN = 'BEFORE') THEN IF (TG_OP = 'UPDATE') THEN op = 'UPDATE_BEFORE'; END IF; INSERT INTO cdc_test VALUES (DEFAULT,DEFAULT,op,OLD.*); ELSE IF (TG_OP = 'UPDATE') THEN op = 'UPDATE_AFTER'; END IF; INSERT INTO cdc_test VALUES (DEFAULT,NEW.*); END IF; IF (TG_OP = 'DELETE') THEN RETURN OLD; ELSE RETURN NEW; END IF; END;
这是当前编写的方式,我将不得不为每个表编写一个单独的触发器函数.我想使用TG_TABLE_NAME来动态构建我的INSERT语句,并在其前面加上’cdc_’,因为所有表都遵循相同的命名约定.然后我可以让每个表调用的每个触发器只有一个函数.
EXECUTE 'INSERT INTO ' || TG_RELID::regclass::text || ' SELECT ($1).*' USING NEW;
使用第8.2页,您有一个问题:
>无法动态访问NEW / OLD列.你得知道
写入触发器功能时的列名.
>在EXECUTE内部看不到NEW / OLD.
>执行..使用尚未出生.
然而,有一个技巧.
系统中的每个表名都可以作为同名的复合类型.因此,您可以创建一个将NEW / OLD作为参数并执行该功能的函数.您可以在每个触发事件上动态创建和销毁该函数:
触发功能:
CREATE OR REPLACE FUNCTION trg_cdc() RETURNS trigger AS $func$ DECLARE op text := TG_OP || '_' || TG_WHEN; tbl text := quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME); cdc_tbl text := quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident('cdc_' || TG_TABLE_NAME); BEGIN EXECUTE 'CREATE FUNCTION f_cdc(n ' || tbl || ',op text) RETURNS void AS $x$BEGIN INSERT INTO ' || cdc_tbl || ' SELECT op,(n).*; END $x$LANGUAGE plpgsql'; CASE TG_OP WHEN 'INSERT','UPDATE' THEN PERFORM f_cdc(NEW,op); WHEN 'DELETE' THEN PERFORM f_cdc(OLD,op); ELSE RAISE EXCEPTION 'UnkNown TG_OP: "%". Should not occur!',TG_OP; END CASE; EXECUTE 'DROP FUNCTION f_cdc(' || tbl || ',text)'; IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF; END $func$ LANGUAGE plpgsql;
触发:
CREATE TRIGGER cdc BEFORE INSERT OR UPDATE OR DELETE ON my_tbl FOR EACH ROW EXECUTE PROCEDURE trg_cdc();
表名必须像用户输入一样对待.使用quote_ident()来防止sql注入.
但是,这样您就可以为每个触发事件创建和删除一个函数.相当大的开销,我不会那样做.你将不得不抽真空一些目录表.
中间地带
Postgresql支持function overloading.因此,每个具有相同基本名称(但不同参数类型)的表的一个函数可以共存.通过在创建触发器的同时为每个表创建一次f_cdc(..),您可以占据中间位置并显着降低噪声.这是每张桌子的一个小功能.您必须观察表定义的更改,但表不应经常更改.从触发器功能中删除CREATE和DROP FUNCTION,达到一个小巧,快速和优雅的触发器.
我可以看到自己在第8.2页中这样做.除了我不能再看到自己在第8.2页做任何事情.它有reached end of life in December 2011.也许你可以以某种方式升级.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。