PostgreSQL에서 개정판을 추적합니다
-
20-09-2019 - |
문제
테이블에서 기록 수정을 추적해야합니다. 내가 한 일은 첫 번째에서 물려 받고 개정 카운터를 추가하는 두 번째 테이블을 만드는 것입니다.
CREATE TABLE A (
id SERIAL,
foo TEXT,
PRIMARY KEY (id));
CREATE TABLE B (
revision INTEGER NOT NULL) INHERITS (A);
그런 다음 A가 삽입/업데이트 될 때마다 테이블 B를 업데이트하는 트리거를 만들었습니다. 내가 알아낼 수없는 것은 B.revision을 만드는 방법입니다. 각 ID에 대해 개별 "시퀀스"를 유지하는 것입니다.
예 : 표 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();
해결책
주문을 위해 버전 번호가 필요하고 각 식별자마다 하나씩 증가하는 정수가 필요하지 않은 경우, 가장 쉬운 방법은 개정 시퀀스를 사용하고 추적을 수행하는 것입니다. 당신을 위한:
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)
다른 팁
내 제안은 다음과 같습니다.
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;
나는 "찾을 수없는 경우"를 Coalesce로 바꾸었고, 기존 개정이 없으면 "0"을 선택할 것입니다. 그런 다음 B The Row에 삽입 한 개정판으로 삽입됩니다.
상속에주의하십시오 : "Only"키워드를 사용하여 선택하고 업데이트 할 때 다음과 같이 자신을 제한해야합니다.
select * from only A
update only A set foo = ... where id = ...
다음은 과거에 사용한 Postgres 용 Rich Aduit 패키지입니다. 감사 트리거. 업데이트 유형 (삽입, 업데이트, 삭제) 및 업데이트 전후 값을 추적합니다.
--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