在Postgres中创建一个触发器,它将一条记录插入到另一个添加了列的表中

时间:2015-12-20 07:44:04

标签: postgresql triggers

我在postgres中创建了这两个表,

CREATE TABLE EMPLOYEE(
   ID           INT             PRIMARY KEY NOT NULL,
   NAME         VARCHAR(100)    NOT NULL,
   ADDRESS      VARCHAR (250)   NOT NULL
);


CREATE TABLE HIST_EMPLOYEE(
   HISTORYNUM   INT             NOT NULL,
   ID           INT             NOT NULL,
   NAME         VARCHAR(100)    NOT NULL,
   ADDRESS      VARCHAR (250)   NOT NULL
);

..所以每当我想在EMPLOYEE表中插入,更新或删除记录时,该记录都应插入HIST_EMPLOYEE表中。无论是单行还是多行

..我知道这个网站有很多答案..但问题是我在我的HISTORY表HIST_EMPLOYEE中添加了一个列...这就是为什么我不能使用这个脚本发布的答案,

insert into hist_employee select * from employee

...这是我迄今为止开始的,但它有很多错误..

TRIGGER

CREATE TRIGGER insertHistory
    AFTER INSERT OR UPDATE ON employee   --MAIN TABLE
        EXECUTE PROCEDURE insertHistory('hist_employee');  --HISTORY TABLE

TRIGGER FUNCTION

CREATE OR REPLACE FUNCTION insertHistory() RETURNS TRIGGER AS 
$func$
    BEGIN
       EXECUTE format('insert into %I select * from %I', TG_ARGV[0] ,TG_TABLE_NAME );
       return null;
    END;
$func$ 
LANGUAGE plpgsql;
  

注意:

     
      
  1. 此触发器也应该适用或足够灵活,以便在具有不同列集的其他表上实现。
  2.   
  3. HISTORYNUM列每个ID都是唯一的,

  4.   
  5. 并且,是否可以在一个触发器中组合这些3, AFTER INSERT,AFTER UPDATE,BEFORE DELETE ..

  6.   

感谢所有回复的人......如果你发现我的问题太模糊了

2 个答案:

答案 0 :(得分:2)

我认为列historynum使用起来太麻烦了。 我建议用时间戳替换它。 您还可以添加一个指示操作类型的列。

create table employee (
    id int primary key,
    name text not null,
    address text not null);

create table employee_history (
    id int,
    name text not null,
    address text not null,
    modified_at timestamp,
    operation text);

您必须在之前使用触发器才能访问当前修改/删除的行。

create or replace function trigger_on_employee()
returns trigger language plpgsql
as $function$
begin
    if tg_op = 'DELETE' then
        insert into employee_history
        select old.*, current_timestamp, tg_op;
        return old;
    else
        insert into employee_history
        select new.*, current_timestamp, tg_op;
        return new;
    end if;
end; $function$;

create trigger trigger_on_employee
  before insert or update or delete
  on employee
  for each row
  execute procedure trigger_on_employee();

一些测试:

insert into employee values 
(1, 'John', 'Berlin'),
(2, 'Adam', 'Paris'),
(3, 'Mike', 'London');

update employee
set name = 'Anna'
where id = 1;

delete from employee
where id = 2;

select * 
from employee_history
order by modified_at;

 id | name | address |        modified_at         | operation 
----+------+---------+----------------------------+-----------
  1 | John | Berlin  | 2015-12-20 16:26:35.703232 | INSERT
  2 | Adam | Paris   | 2015-12-20 16:26:35.703232 | INSERT
  3 | Mike | London  | 2015-12-20 16:26:35.703232 | INSERT
  1 | Anna | Berlin  | 2015-12-20 16:26:35.750609 | UPDATE
  2 | Adam | Paris   | 2015-12-20 16:26:35.761521 | DELETE
(5 rows)

答案 1 :(得分:0)

  1. 过度推广你的触发功能,恕我直言,真的没有什么可以获得的,尤其是像这一个短的触发功能。保持简单,为每个历史表编写一个新的触发函数。
  2. HISTORYNUM列?没关系;我看到了。但不知道该如何处理它。
  3. 否。单个触发器必须 BEFORE AFTER。但可以声明多个调用相同函数的触发器。
  4. 如果不这样做,你写的触发函数几乎肯定会遇到“变异表”错误。此外,您似乎正在尝试将“当前”表的整个内容复制到“历史”表 每次 更新发生。您已在伪记录INSERT和{{1}中拥有新数据(适用于UPDATEUPDATE)和旧数据(适用于DELETENEW) }} 分别。为什么不利用它?

    除此之外,你说你有

      

    这么多错误......

    也许如果你告诉我们其中的一些,我们可以帮你修复它们。