Historik med triggers

At opbygge en historik kræver at en tabel som minumum indeholder oplysninger om hver rækkes gyldighedsperiode.

Opret en eksempeltabel

Det er nyttigt hvis man ikke vil eksperimentere på sine egne data.

CREATE TABLE test_pkt (
  fid SERIAL,
  geom geometry(Point, 25832),
  navn CHARACTER VARYING(32),
  CONSTRAINT test_pkt_pkey PRIMARY KEY (fid)
);

INSERT INTO test_pkt(geom, navn) VALUES
(ST_GeomFromText('POINT(0 0)',25832), 'Punkt 1'),
(ST_GeomFromText('POINT(0 1)',25832), 'Punkt 2'),
(ST_GeomFromText('POINT(0 2)',25832), 'Punkt 3'),
(ST_GeomFromText('POINT(0 3)',25832), 'Punkt 4'),
(ST_GeomFromText('POINT(0 4)',25832), 'Punkt 5'),
(ST_GeomFromText('POINT(0 5)',25832), 'Punkt 6'),
(ST_GeomFromText('POINT(0 6)',25832), 'Punkt 7');

Klargøring

Vi har nu en tabel, der i princippet kunne være hvilken som helst slags data. Nu skal den gøres klar til historik

Tilføj ekstra felter og sæt alle nuværende objekter som gyldige

ALTER TABLE test_pkt
ADD COLUMN version_id uuid DEFAULT uuid_generate_v4() NOT NULL,
ADD COLUMN registrering_fra TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
ADD COLUMN registrering_til TIMESTAMP DEFAULT NULL,
ADD COLUMN handling character varying(100) DEFAULT NULL,
ADD COLUMN bruger character varying(100) DEFAULT NULL
;

UPDATE test_pkt SET gyldig_fra = '1900-01-01 00:00:00', handling = 'Indlæst';

Ændr tabellens primære nøgle

ALTER TABLE test_pkt DROP CONSTRAINT test_pkt_pkey;
ALTER TABLE test_pkt ADD PRIMARY KEY (fid, version_id);

Lav et view, der filtrerer således at kun nuværende objekter vises

CREATE VIEW test_pkt_fv AS
SELECT fid, geom, navn,
       version_id
FROM test_pkt
WHERE gyldig_fra <= CURRENT_TIMESTAMP AND (gyldig_til IS NULL OR gyldig_til >= CURRENT_TIMESTAMP);

Opsætning af trigger

Opdateringsfunktion

For at kunne lave en trigger skal den første have en funktion, altså det noget der sker når noget andet sker. Det er det her der er det "svære".

Nedenstående håndterer kun slette-operationer.

CREATE OR REPLACE FUNCTION test_pkt_hist_trg()
  RETURNS trigger AS
$BODY$
  BEGIN
    IF (TG_OP = 'DELETE') THEN
        -- Return "0 rows deleted" IF NOT EXISTS

        IF NOT EXISTS
           (SELECT '1' FROM test_pkt
                WHERE fid = OLD.fid  AND version_id=OLD.version_id
                    AND (registrering_til IS NULL
                        OR gyldig_registrering >= CURRENT_TIMESTAMP))
            )
            THEN
                RETURN NULL;
        END IF;

        UPDATE test_pkt
            SET gyldig_til = current_timestamp,
                handling = 'Slettet',
                bruger = current_user
            WHERE version_id=OLD.version_id;

       RETURN OLD;
    END IF;
  END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

ALTER FUNCTION test_pkt_hist_trg()
  OWNER TO postgres;

Selve triggeren

Selve triggeren sættes op til at vores funktion kører når (forstået som I STEDET FOR) vores view bliver udsat for INSERT, UPDATE eller DELETE.

Triggeren håndterer det rækkevis.

CREATE TRIGGER test_pkt_hist_trg_iud INSTEAD OF INSERT OR UPDATE OR DELETE
   ON public.test_pkt_fv FOR EACH ROW
   EXECUTE PROCEDURE public.test_pkt_hist_trg();

results matching ""

    No results matching ""