首页 > 解决方案 > 动态列名 postgresql 触发器

问题描述

我正在尝试创建一个动态审计触发器,该触发器从信息架构中读取 column_name 并将该列已更改的列插入到审计表中。到目前为止,我有以下代码:

     CREATE OR REPLACE FUNCTION dynamic_column_audit()
        RETURNS trigger
        LANGUAGE 'plpgsql'
        COST 100
        VOLATILE NOT LEAKPROOF AS $BODY$
        <<main_function>>
    
    declare
    table_name_tr text;
    table_schema_tr text;
    
    column_name_trigger text;
    old_column_name_trigger record;
    new_column_name_trigger record;
    begin
    -- variables
    table_name_tr := TG_TABLE_NAME;
    table_schema_tr := TG_TABLE_SCHEMA;
    
    <<loop_sql>>
        FOR column_name_trigger IN (SELECT c.column_name FROM information_schema.columns c WHERE c.table_schema = table_schema_tr and c.table_name = table_name_tr ORDER BY ordinal_position asc)
            LOOP
            
            RAISE INFO E'\n Column name: %, table_name: %', column_name_trigger , table_schema_tr||'.'||table_name_tr;
            IF (TG_OP = 'UPDATE') THEN
            
            INSERT INTO my_loggingtable (operation, table_schema, table_name, column_name, old_value, new_value) 
            VALUES (TG_OP, table_name_tr, table_schema_tr, column_name_trigger, OLD.||column_name_trigger, NEW.||column_name_trigger);
end if;
    END LOOP loop_sql;
    return new;
    end main_function;
    $BODY$;

我正在尝试看看是否有可能做类似 NEW 的事情。+ column_name 或 OLD> + column_name 来自循环,而不是硬编码每个表的列名值。

这背后的想法是在不一直添加名称的情况下为大约 20 个表执行审计触发器,这是不可能的。

标签: sqlpostgresqltriggers

解决方案


您可以使用这样的构造:

DECLARE
   newval text;
BEGIN
   EXECUTE format(
              'SELECT ($1::%I).%I',
              table_name,
              column_name
           )
      INTO newval
      USING NEW;
END;

推荐阅读