문제

테이블에서 기록 수정을 추적해야합니다. 내가 한 일은 첫 번째에서 물려 받고 개정 카운터를 추가하는 두 번째 테이블을 만드는 것입니다.

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top