Domanda

Devo tenere traccia delle revisioni di record in una tabella. Quello che ho fatto è creare una seconda tabella che eredita dal primo e aggiunge un contatore di revisione.

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

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

Poi ho creato un trigger che avrebbe aggiornare la tabella B è inserita / aggiornata ogni volta A. Quello che non riesco a capire è come fare B.revision mantenere un individuo "sequenza" per ogni id.

Esempio: tabella A ha 2 file, i & j
. Mi è stato aggiornato 3 volte e dovrebbe avere 3 revisioni:. (1, 2, 3)
j è stato aggiornato 2 volte e dovrebbe avere due revisioni:. (1, 2)

Ecco quello che ho finora, forse sto andando sulla strada sbagliata e qualcuno mi può aiutare!

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();
È stato utile?

Soluzione

Se avete bisogno i numeri di versione solo per l'ordinazione, e non specificamente bisogno di loro per essere un numero intero che aumentano di uno per ogni identificatore, il modo più semplice per farlo è quello di utilizzare una sequenza per la revisione e giusto lasciarlo fare il tracking per voi:

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();

Poi fare gli inserti come al solito:

    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)

Quindi, è possibile ottenere tutte le revisioni per una data riga in questo modo:

    try=# select * from b where id = 1 order by revision;
     id | foo | revision 
    ----+-----+----------
      1 | you |        1
      1 | you |        3
    (2 rows)

Altri suggerimenti

Ecco il mio consiglio:

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;

Ho cambiato il "se non trovato" in un coalesce, che sceglierà il "0" se non v'è alcuna revisione esistente. Poi, inserisco nella riga B, con la revisione incrementato.

Fate attenzione con la tua eredità: è necessario utilizzare la parola chiave "solo" per limitarsi alla Un tavolo al momento della selezione e l'aggiornamento, come ad esempio:

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

Ecco un ricco pacchetto di funzionalità per Aduit postgres che ho usato in passato: Audit trigger . Tiene traccia del tipo di aggiornamento (inserimento, aggiornamento, cancellazione), così come la prima e dopo i valori per l'aggiornamento.

--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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top