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

标签 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 表中。不管是单行还是多行

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

insert into hist_employee select * from employee

...这是我到目前为止开始的,但它有很多错误..

触发

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

触发功能

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;

NOTE:

  1. This trigger should be also applicable or flexible enough to be implemented on other tables with different set of columns.
  2. HISTORYNUM column is unique per id,

  3. And, is it possible to combine these 3, AFTER INSERT, AFTER UPDATE, BEFORE DELETE .. in one trigger ??

感谢所有愿意回答的人..如果您觉得我的问题太含糊,抱歉

最佳答案

我认为 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)

关于postgresql - 在 Postgres 中创建一个触发器,它将一条记录插入到另一个带有添加列的表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34378929/

相关文章:

jQuery 在开始触发之前检查悬停状态

c# - 使用共享托管创建定时事件?

postgresql - 使用 Hasura 在 postgresql 中搜索 jsonb 字段

ruby-on-rails - Model.sum 在使用 :include (rails 2. 3.8 时返回不准确的和

sql - PostgreSQL:根据排序顺序仅选择每个 id 的第一条记录

MySQL事务和触发器

mysql - 在更新后触发器中使用 OLD 变量时出现问题

postgresql - 点击流:PostgreSQL Crosstab for UTM Path by User_ID

php - Doctrine 中的 Exception(AbstractPostgreSQLDriver->convertException) 用于在 postgresql 中插入数据(使用 symfony)

MySQL 触发器中的 IF 语句