PL / pgSQL: как использовать IF NEW.<> СТАРЫЙ - PullRequest
0 голосов
/ 06 октября 2018

Я довольно новичок в программировании на PL / pgSQL.У меня есть требование ведения журнала обновленных столбцов в моей таблице

Таблица

create table sample_table(name varchar(15),city varchar(15),age int,mail varchar(20) primary key); 

Таблица аудита

create table sample_table__audits_dynamicols(mail varchar(20), columnchanged varchar(10), oldvalue varchar(10), changed_on timestamp(6) NOT NULL)

Функция триггера

CREATE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS $BODY$DECLARE
       _colname text;
       _tablename varchar(15) := 'sample_table';
       _schema varchar(15) := 'public';
       _changed_on time := now();
    BEGIN
      FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename LOOP  
         IF NEW._colname <> OLD._colname THEN
            INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
            VALUES(OLD.mail,_colname,OLD.:_colname,_changed_on);
         END IF;
      END LOOP;
     RETURN NEW;
    END$BODY$
    LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;

Триггер

create TRIGGER log_sample_table_allchanges
  BEFORE UPDATE
  ON SAMPLE_TABLE
  FOR EACH ROW
  EXECUTE PROCEDURE log_sample_table_allchanges();

Требование: при каждом изменении значения столбца я хочу зарегистрировать его как

(почта, имя столбца, значение столбца, дата)

Например:

insert into sample_table (name, mail, city, age) values('kanta','mk@foo.com','hyd',23);
insert into sample_table (name, mail, city, age) values('kmk','mk@gmail.com','hyd',23);

Поэтому, когда я обновляю, как показано ниже

update sample_table set age=24 where mail='mk@foo.com';
update sample_table set city='bza' where mail='mk@gmail.com'

, я хочу, чтобы таблица аудита записывала как

(mk@foo.com,age,23, timestamp) 
(mk@gmail.com, city, hyd, timestamp)

Прямо сейчас я сталкиваюсь с проблемой сравнения столбцов в моем Триггерефункция.Пожалуйста, помогите мне исправить мою функцию триггера, чтобы удовлетворить мои требования.

1 Ответ

0 голосов
/ 06 октября 2018

Вы можете использовать EXECUTE для динамического получения значений столбцов и сравнения.

CREATE OR REPLACE FUNCTION public.log_sample_table_allchanges() RETURNS trigger AS 
    $BODY$
      DECLARE
       _colname text;
       _tablename varchar(15) := 'sample_table';
       _schema varchar(15) := 'public';
       _changed_on timestamp := now();
       _old_val text;
       _new_val text;
    BEGIN
      FOR _colname IN SELECT column_name FROM information_schema.Columns WHERE table_schema = _schema AND table_name = _tablename
       LOOP  
          EXECUTE 'SELECT $1.' || _colname || ', $2.' || _colname
           USING OLD,NEW
          INTO _old_val, _new_val; --get the old and new values for the column.

          IF _new_val <> _old_val THEN
            INSERT INTO sample_table__audits_dynamicols(mail,columnchanged, oldvalue ,changed_on)
            VALUES(OLD.mail,_colname,_old_val,_changed_on);
         END IF;
      END LOOP;
     RETURN NEW;
    END$BODY$
    LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;

Я не уверен, почему вы определили mail как PRIMARY KEY в аудитахтаблица, это приведет к нарушению unique constraint, если одно и то же письмо будет обновлено дважды.

...