如何在PostgreSQL UPDATE触发器函数中获取更改的列集?

ijnw1ujt  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(164)

我有一个简单的函数,在更新PostgreSQL 14表时触发:

CREATE OR REPLACE FUNCTION track_changes() RETURNS TRIGGER AS $body$

BEGIN
    raise notice 'old is: "%"', OLD;
    raise notice 'new is: "%"', NEW;
END;
$body$
LANGUAGE plpgsql
;

CREATE TRIGGER update_trigger
AFTER UPDATE ON students
FOR EACH ROW EXECUTE PROCEDURE track_changes();

但是,该函数旨在用于许多不同的表-即我不知道哪些栏目是可用的。我如何在触发器函数中计算OLDNEW之间不同的列集-例如作为recordrow或甚至JSONB值?

2guxujil

2guxujil1#

你必须查询元数据:

CREATE OR REPLACE FUNCTION changed_columns() RETURNS trigger
   LANGUAGE plpgsql AS
$$DECLARE
   col name;
   changed_cols text[] := ARRAY[]::text[];
   changed boolean;
BEGIN
   FOR col IN
      /* get the columns of the table */
      SELECT attname
      FROM pg_attribute
      WHERE attrelid = TG_RELID
        AND attnum > 0
        AND NOT attisdropped
   LOOP
      /* compare the column in OLD and NEW */
      EXECUTE
         format(
            'SELECT (($1::%1$s).%2$I) IS DISTINCT FROM (($2::%1$s).%2$I)',
            TG_RELID::regclass,
            col
         )
         USING OLD, NEW
         INTO changed;

      IF changed THEN
         changed_cols := changed_cols || col::text;
      END IF;
   END LOOP;

   RAISE NOTICE 'changed columns: %',
                array_to_string(changed_cols, ', ');

   /* proceed with the UPDATE */
   RETURN NEW;
END;$$;
ndh0cuux

ndh0cuux2#

下面是一个基于JSONB的建议。将newold转换为JSONB,以便提取键(这些是表的列名)并迭代它们。

create or replace function changed_columns()
returns trigger language plpgsql as
$function$
declare
  new_jb jsonb := to_jsonb(new); 
  old_jb jsonb := to_jsonb(old); 
  running_column text;
  columns_list text[] := '{}';
begin
 for running_column in select jsonb_object_keys(new_jb) loop
   if (new_jb -> running_column <> old_jb -> running_column) then
     columns_list := columns_list || running_column;
   end if;
 end loop;
 raise notice 'changed columns: %', array_to_string(columns_list, ',');
 -- or use columns_list for something more useful
 return null; -- use it in an after update trigger
end;
$function$;

相关问题