Avatar billede nemezis_aalborg Nybegynder
20. april 2005 - 17:07 Der er 5 kommentarer og
1 løsning

Triggers til mirroring af data

Hejsa, jeg har en database 'min_database', der ser sådan ud:

min_database:

    table_1 (integer, character varying(30),
        character varying(30), character varying(2),
        character varying(40)):

        id |username  |attribute    |op  |value
        ---------------------------------------
        7  |baek      |User-Password|:=  |noget

    table_2 (integer, character varying(20), character varying(50)):

        id |user      |pass
        --------------------
        7  |baek      |noget

    table_3 (bigint, character varying(100), character varying(34)):

        user_idnr |userid      |passwd
        -------------------------------------
        7        |baek        |noget

Idéen er at jeg vil lave triggers sådan at når noget ændres i table_1, så opdateres de pågældende attributter også i de andre

tables. Grunden til dette er at jeg har binaries, som kræver nogle helt bestemte tabeller.

Det er meningen at table_2(user) og table_3(userid) skal svare til table_1(username). table_2(pass) og table_3(passwd) skal

svare til table_1(value). table_1(id), table_2(id), og table_3(user_idnr) tælles automatisk op og er primary key.

Altså når der indsættes i table_1 skal der også automatisk indsættes i table_2 og table_3. Tilsvarende gælder for delete. Med

hensyn til update er det kun password der kan ændres, men dette skal naturligvis og gøres.

Der bliver kun indsat og ændret data i table_1, mens de andre ikke bliver ændret direkte.

Er kommet frem til at jeg skal lave noget allá:
CREATE TRIGGER table_1_insert_trigger AFTER INSERT ON table_1
FOR EACH { ROW | STATEMENT }
    EXECUTE PROCEDURE func ( arguments );

CREATE TRIGGER table_1_update_trigger AFTER UPDATE ON table_1
FOR EACH { ROW | STATEMENT }
    EXECUTE PROCEDURE func ( arguments );

CREATE TRIGGER table_1_delete_trigger AFTER DELETE ON table_1
FOR EACH { ROW | STATEMENT }
    EXECUTE PROCEDURE func ( arguments );

Men er lidt i tvivl om hvordan dette helt præcist skal gøres, og hvordan functionerne skal se ud :/

/ Søren
Avatar billede kichian Nybegynder
21. april 2005 - 13:40 #1
Hej følgende eksempel virker på version 8.

Jeg har valgt at lægge logikken i en trigger og function.

CREATE OR REPLACE FUNCTION table_1_trigger()
  RETURNS "trigger" AS
$BODY$
BEGIN
IF TG_OP = 'INSERT' THEN
    INSERT INTO table_2 VALUES (NEW.id, NEW.username, NEW.value);
    INSERT INTO table_3 VALUES (NEW.id, NEW.username, NEW.value);
ELSE
    IF TG_OP = 'UPDATE' THEN
        UPDATE table_2 SET pass = NEW.value WHERE id = NEW.id;
        UPDATE table_3 SET passwd = NEW.value WHERE user_idnr = NEW.id;
    ELSE
        DELETE FROM table_2 WHERE id = OLD.id;
        DELETE FROM table_3 WHERE user_idnr = OLD.id;
    END IF;
END IF;

RETURN NEW;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

CREATE TRIGGER table_1_auto
  AFTER INSERT OR UPDATE OR DELETE
  ON table_1
  FOR EACH ROW
  EXECUTE PROCEDURE table_1_trigger();
Avatar billede kichian Nybegynder
21. april 2005 - 14:46 #2
Og det jeg mente var, at jeg havde valgt at lægge logikken i een trigger og een funktion, da synkroniseringen er en enhedsoperation.
Avatar billede nemezis_aalborg Nybegynder
21. april 2005 - 21:33 #3
Prøver lige... har desværre først mulighed på mandag :)
Avatar billede nemezis_aalborg Nybegynder
24. april 2005 - 15:41 #4
Postgre siger:
----------------
SQL error:


ERROR:  syntax error at or near "$" at character 71

In statement:


CREATE OR REPLACE FUNCTION table_1_trigger()
  RETURNS "trigger" AS
$BODY$
BEGIN
IF TG_OP = 'INSERT' THEN
    INSERT INTO table_2 VALUES (NEW.id, NEW.username, NEW.value);
    INSERT INTO table_3 VALUES (NEW.id, NEW.username, NEW.value);
ELSE
    IF TG_OP = 'UPDATE' THEN
        UPDATE table_2 SET pass = NEW.value WHERE id = NEW.id;
        UPDATE table_3 SET passwd = NEW.value WHERE user_idnr = NEW.id;
    ELSE
        DELETE FROM table_2 WHERE id = OLD.id;
        DELETE FROM table_3 WHERE user_idnr = OLD.id;
    END IF;
END IF;

RETURN NEW;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

CREATE TRIGGER table_1_auto
  AFTER INSERT OR UPDATE OR DELETE
  ON table_1
  FOR EACH ROW
  EXECUTE PROCEDURE table_1_trigger();
----------------
Avatar billede kichian Nybegynder
25. april 2005 - 13:43 #5
Det lader til at du kører med en version 7 af postgresql.

Prøv i stedet:

CREATE OR REPLACE FUNCTION table_1_trigger()
  RETURNS "trigger" AS
'BEGIN
IF TG_OP = ''INSERT'' THEN
    INSERT INTO table_2 VALUES (NEW.id, NEW.username, NEW.value);
    INSERT INTO table_3 VALUES (NEW.id, NEW.username, NEW.value);
ELSE
    IF TG_OP = ''UPDATE'' THEN
        UPDATE table_2 SET pass = NEW.value WHERE id = NEW.id;
        UPDATE table_3 SET passwd = NEW.value WHERE user_idnr = NEW.id;
    ELSE
        DELETE FROM table_2 WHERE id = OLD.id;
        DELETE FROM table_3 WHERE user_idnr = OLD.id;
    END IF;
END IF;

RETURN NEW;
END;
'
  LANGUAGE 'plpgsql' VOLATILE;
Avatar billede nemezis_aalborg Nybegynder
25. april 2005 - 17:52 #6
top nice
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester