Trigger für History einer Tabelle bei Update

Tachchen mal wieder!!!

Habe mal Wieer eine Frage…

Ich versuche einen Trigger zu schreiben (in pl/pgsql) der mir bei eiem Update auf der einen Tabelle, die Daten in eine History_Tabelle schreibt( aber nur wenn die alten Daten gegenüber den neuen Daten unterschiedlich sind). Als PK(oder UNIQUE) der History_Tabelle will ich den Timestamp nehmen.

CODE der beiden Tabellen:

CREATE TABLE “public”.“pcstandort” (
“hostname” VARCHAR(30) NOT NULL,
“geb” VARCHAR(5) NOT NULL,
“raum” VARCHAR(6) NOT NULL,
CONSTRAINT “gebaeude_pkey” PRIMARY KEY(“hostname”, “geb”, “raum”),
CONSTRAINT “pcstandort_fk” FOREIGN KEY (“hostname”)
REFERENCES “public”.“lastlogin”(“hostname”)
ON DELETE CASCADE
ON UPDATE NO ACTION
NOT DEFERRABLE
) WITHOUT OIDS;

CREATE TRIGGER “pcstandort_histo_tr” BEFORE UPDATE
ON “public”.“pcstandort” FOR EACH ROW
EXECUTE PROCEDURE “public”.“pcstandorthisto”();
BEGIN
if raum <> old.raum and geb <> old.geb THEN
INSERT into public.pcstandort_histo(timestampadd,hostname,geb,raum) VALUES(TIMESTAMP,old.hostname,old.geb,old.raum)
return NEW;
end if;
END;

CREATE TABLE “public”.“pcstandort_histo” (
“hostname” VARCHAR(30),
“geb” VARCHAR(5),
“raum” VARCHAR(6),
“timestampadd” TIMESTAMP WITHOUT TIME ZONE NOT NULL,
CONSTRAINT “pcstandort_histo_gebaeude_pkey” PRIMARY KEY(“timestampadd”)
) WITHOUT OIDS;


Mit NEW… gibt es probs

Hatte ein Bsp. im Netz gefunden…
Bsp CODE

\

> CREATE TRIGGER "table_trigger_histo" AFTER UPDATE
> ON "public"."table_inv" FOR EACH ROW
> EXECUTE PROCEDURE "public"."table_function_histo"();
>
> CREATE OR REPLACE FUNCTION "public"."table_function_histo" () RETURNS
> trigger AS'
> BEGIN
> INSERT INTO table_histo
> (
> inv_id,
> modell_id,
> ...
> ) VALUES (
> old.inv_id,
> old.modell_id,
> old. ....
> )

RETURN NEW;

> end;

Konnte leider diese Bsp. nicht nutzen, weil edliche Syntax-Fehler da waren(außer die ganze "......" Geschichte, weil so schlau war ich auch.

Hallo raptor0,

Kannst Du mal mitteilen, wie Du testes und womit?


PS: Namen und Variable muss Du nicht in ‘"’ setzen, ausser man will Namen mit Groß- und Kleinschreibung verwenden. Defaultmäßig werden die Namen intern ohne ‘"’ immer in Kleinschreibung umgewandelt.



mfg

fristo

Zur Zeit nutze ich eine Testversion von EMS

Darf ich dich dazu mal auf ein fertiges Modul verweisen?

http://pgfoundry.org/projects/tablelog/

Logging inklusive und Funktionen, um den Zustand einer Tabelle in der Vergangenheit darzustellen.

Support ist bei mir zu haben :wink:

Hallo raptor0,

zum Testen solltest Du dir z. B. PgAdmin installieren. Im “Allgemeine SQL-Abfragen”-Fenster (Icon SQL) kann Du Deinen Code im Detail testen. Im oberen Teil gibt Du z. B. den Code für die Definition von CREATE TABLE ein. Nach Ausführung des Codes kannst Du im unteren Teil des Fensters sehen ob Code Fehler enthielt oder korrekt war.


Folgende Fehler sind erkennbar:

BEGIN
if raum <> old.raum and geb <> old.geb THEN
INSERT into public.pcstandort_histo(timestampadd,hostname,geb,raum) VALUES(TIMESTAMP,old.hostname,old.geb,old.raum)
return NEW;
end if;
END

Hier fehlt erstmal der Funktionsrumf. Sollte dieses Code der Funktion pcstandorthisto() sein muss Du statt “old” “new” verwenden, da es in der Definition des Triggers “BEFORE UPDATE” heißt. Details wann “new” oder “old” eingesetzt werden muss, kannst Du in der Doku unter “Triggerprozeduren” nachlesen. TIMESTAMP ist ein TYPE und keine Funktion!


CREATE OR REPLACE FUNCTION “public”.“table_function_histo” () RETURNS
trigger AS’
BEGIN
INSERT INTO table_histo
(
inv_id,
modell_id,

) VALUES (
old.inv_id,
old.modell_id,
old. …
)

RETURN NEW;

end;

Hier muss es RETURN OLD heißen.



mfg

fristo

An alle,…

habe es geschafft… grins

Lag wohl daran, dass ich im EMS an den falschen Stellen bzw. in der falschen Ansicht programmiert habe.

  1. Die Funktion erstellen:

CREATE OR REPLACE FUNCTION “public”.“pcstandorthisto_trf” () RETURNS SETOF trigger AS
$body$
begin
if new.geb<>old.geb or new.raum<>old.raum THEN
insert into pcstandorthisto values(old.hostname,old.geb,old.raum,current_timestamp);
end if;
return new;
end;
$body$
LANGUAGE ‘plpgsql’ VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

  1. Den Trigger erstellen und die geschriebene Funktion auswählen:

CREATE TRIGGER “pcstandorthisto_tr” AFTER UPDATE
ON “public”.“pcstandort” FOR EACH ROW
EXECUTE PROCEDURE “public”.“pcstandorthisto_trf”();

Dann sollte es auch mit dem Nachbarn klappen…