Postgres создает универсальную функцию на весь стол

У меня есть несколько таблиц БД. Я хочу написать универсальную функцию postgres для копирования строк в таблицы истории У меня есть таблицы:

table1
table1_h

table2
table2_h

Я написал функцию (с помощью stackru)

CREATE OR REPLACE FUNCTION copy_history_f() RETURNS TRIGGER AS
$BODY$
  DECLARE
    tablename_h text:= TG_TABLE_NAME || '_h';
  BEGIN
     EXECUTE 'INSERT INTO  ' || quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(tablename_h) || ' VALUES (' || OLD.* ||')';
    RETURN NULL;
  END; 
$BODY$
LANGUAGE plpgsql VOLATILE;

И функции создаются, но после обновления есть ошибка.

ERROR:  syntax error at or near ","
ROW 1: ...RT INTO  table1_h VALUES ((12,,,0,,"Anto...

Я знаю, где ошибка в этой вставке, но я не знаю, как это исправить. Структурные таблицы table1 и table1_h идентичны, но у table1_h есть еще один столбец (id_h)

Можете ли вы помочь мне, как я могу создать функцию PSQL?

Спасибо тебе.

2 ответа

drop table if exists t;
drop table if exists t_h;
drop function if exists ftg();

create table t(i serial, x numeric);
insert into t(x) values(1.1),(2.2);

create table t_h(i int, x numeric);

create function ftg() returns trigger language plpgsql as $ftg$
declare
  tablename_h text:= TG_TABLE_NAME || '_h';
begin
  execute format($q$ insert into %I.%I select $1.*; $q$, TG_TABLE_SCHEMA, tablename_h) using old;
  return null;
end $ftg$;

create trigger tg_t after delete on t for each row execute procedure ftg();

delete from t where i = 1;
select * from t_h;

dbfiddle

Обновление Это решает вашу проблему, но я думаю, что вы хотите иметь немного больше информации в ваших таблицах истории. Это будет немного сложнее:

drop table if exists t;
drop table if exists t_h;
drop function if exists ftg();

create table t(i serial, x numeric);
insert into t(x) values(1.1),(2.2);

create table t_h(
  hi serial,      -- just ID
  hd timestamp,   -- timestamp
  hu text,        -- user who made changes
  ha text,        -- action
  i int, x numeric
);

create function ftg() returns trigger language plpgsql as $ftg$
declare
  tablename_h text:= TG_TABLE_NAME || '_h';
begin
  execute format(
    $q$
      insert into %I.%I
        select
          nextval(%L || '_hi_seq'),
          clock_timestamp(),
          current_user,
          %L,
          $1.*
    $q$, TG_TABLE_SCHEMA, tablename_h, tablename_h, TG_OP) using old;
  return null;
end $ftg$;

create trigger tg_t after delete or update on t for each row execute procedure ftg();

update t set x = x * 2;
update t set x = x * 2 where i = 2;
delete from t where i = 1;

select * from t_h;

dbfiddle

Я предполагаю, что вы вставляете "старые" значения из table1 в table1_h.

Дополнительный столбец - ваша проблема. Когда вы используете вставку без именования столбцов, вы должны использовать соответствующий номер и тип для вставки.

Вы должны использовать ссылки на столбцы.

например.

Insert into table1_h(column1, column2, column3) 
values (a,b,c)

Рассмотрим значение по умолчанию для дополнительного столбца в таблице table1_h.

Другие вопросы по тегам