отслеживать изменения в postgresql - PullRequest
5 голосов
/ 14 февраля 2010

Я должен отслеживать изменения записей в таблице. Я создал вторую таблицу, которая наследуется от первой и добавляет счетчик ревизий.

CREATE TABLE A (
id SERIAL,
foo TEXT,
PRIMARY KEY (id));

CREATE TABLE B (
revision INTEGER NOT NULL) INHERITS (A);

Затем я создал триггер, который будет обновлять таблицу B каждый раз, когда A вставляется / обновляется. Я не могу понять, как заставить B.revision сохранять индивидуальную «последовательность» для каждого идентификатора.

Пример: таблица A имеет 2 строки, i & j.
я был обновлен 3 раза и должен иметь 3 ревизии: (1, 2, 3).
j обновлялся 2 раза и должен иметь две ревизии: (1, 2).

Вот то, что у меня есть, возможно, я иду по неверному пути, и кто-то может мне помочь!

CREATE OR REPLACE FUNCTION table_update() RETURNS TRIGGER AS $table_update$
    DECLARE
        last_revision INTEGER;
    BEGIN
        SELECT INTO last_revision MAX(revision) FROM B WHERE id = NEW.id;

        IF NOT FOUND THEN
            last_revision := 0;
        END IF;

        INSERT INTO B SELECT NEW.*;

        RETURN NEW;
    END;
$table_update$ LANGUAGE plpgsql;

CREATE TRIGGER table_update
AFTER INSERT OR UPDATE ON A
    FOR EACH ROW EXECUTE PROCEDURE table_update();

Ответы [ 4 ]

7 голосов
/ 14 февраля 2010

Если вам нужны номера версий только для упорядочения, и вам не нужно, чтобы они были целым числом, которое увеличивается на единицу для каждого идентификатора, самый простой способ сделать это - использовать последовательность для ревизии и просто сделать отслеживание для вас:

CREATE TABLE A (
    id SERIAL,
    foo TEXT,
    PRIMARY KEY (id)
);

CREATE TABLE B ( revision SERIAL NOT NULL) INHERITS (A);

CREATE OR REPLACE FUNCTION table_update() RETURNS TRIGGER AS $table_update$
    BEGIN
        INSERT INTO B SELECT NEW.*;
        RETURN NEW;
    END;
$table_update$ LANGUAGE plpgsql;

CREATE TRIGGER table_update
AFTER INSERT OR UPDATE ON A
    FOR EACH ROW EXECUTE PROCEDURE table_update();

Затем вставьте как обычно:

    try=# insert into a (foo) values ('bar');
    INSERT 0 1
    try=# insert into a (foo) values ('bar');
    INSERT 0 1
    try=# update a set foo = 'you' where id = 1;
    UPDATE 2
    try=# select * from b;
     id | foo | revision 
    ----+-----+----------
      2 | bar |        2
      1 | you |        1
      1 | you |        3
    (3 rows)

Таким образом, вы можете получить все ревизии для данной строки следующим образом:

    try=# select * from b where id = 1 order by revision;
     id | foo | revision 
    ----+-----+----------
      1 | you |        1
      1 | you |        3
    (2 rows)
0 голосов
/ 04 января 2014

Вот многофункциональный пакет Aduit для postgres, который я использовал в прошлом: Audit Trigger . Он отслеживает тип обновления (вставка, обновление, удаление), а также значения до и после обновления.

0 голосов
/ 10 мая 2012
--THIS TABLE AUTOMATICALLY INCREMENT THE COLUMN VALUES USING TRIGGER
CREATE TABLE emp_table(
  emp_id int not null,
  emp_name varchar not null,
  emp_rollno int not null,
  primary key(emp_id)
);

--Now create table with three column and emp_id is primary key
--and emp_rollno both are automatically increment in trigger is fired
CREATE or REPLACE FUNCTION emp_fun() RETURNS TRIGGER AS $BODY$
--creating function emp_fun()
DECLARE
BEGIN
  IF(tg_op='INSERT') THEN
    NEW.emp_id=COALESCE((SELECT MAX(emp_id)+1 FROM emp_table), 1);
    NEW.emp_rollno=COALESCE((SELECT MAX(emp_rollno)+1 FROM emp_table), 1);
    --trigger is fired values is automatically increment
END IF;

IF tg_op='DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;
END; $BODY$LANGUAGE PLPGSQL

CREATE TRIGGER emp_fun BEFORE INSERT ON
  emp_table FOR EACH ROW EXECUTE PROCEDURE emp_fun();

INSERT INTO emp_table(emp_name) VALUES('BBB');
--insert the value tanle emp_table
SELECT * FROM emp_table
-- Check the result
0 голосов
/ 14 февраля 2010

Вот мое предложение:

CREATE OR REPLACE FUNCTION table_update() RETURNS TRIGGER AS $table_update$
DECLARE
    last_revision INTEGER;
BEGIN
    SELECT INTO last_revision coalesce(MAX(revision), 0) FROM B WHERE id = NEW.id;

    INSERT INTO B SELECT NEW.*, last_revision + 1;

    RETURN NEW;
END;
$table_update$ LANGUAGE plpgsql;

Я изменил «если не найден» на объединение, которое выберет «0», если не существует ревизии. Затем я вставляю в B строку с увеличенной ревизией.

Будьте осторожны со своим наследованием: вам нужно будет использовать ключевое слово «only», чтобы ограничить себя таблицей A при выборе и обновлении, например:

select * from only A
update only A set foo = ... where id = ...
...