Toon posts:

[Postgres] Update in update trigger

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een trigger gemaakt welke bij INSERTs en UPDATEs uitgevoerd worden. Met INSERTs is er niks aan de hand, en werkt 't goed. Echter, bij het UPDATE'n gaat het fout omdat binnen de trigger dezelfde tabel geupdate wordt. Daardoor wordt de trigger dus voortdurend uitgevoerd, wat dus leidt tot een eindeloze loop.

Hoe kan ik er voor zorgen dat de trigger alleen uitgevoerd wordt voor de gewijzigde rij, en niet voor alle rijen die in de trigger geupdate worden. Kan ik de trigger tijdelijk uitschakelen, of moet ik hem verwijderen en er naar afloop weer in zetten of zoiets?

  • 0528973
  • Registratie: Juni 2003
  • Laatst online: 15-05-2013
Post die trigger is aub...
Een trigger kan als je hem normaal schrijft toch niet in een oneindige loop geraken?

Ik zie nu wat je bedoeld, deze trigger is gemaakt voor die location tabel, waarin je de update doet. Je hebt deze trigger gedefinieerd om uitgevoerd te worden tijdens een insert en een update. In de trigger zelf, doe je ook de tabel location updaten, waardoor je in een oneindige loop geraakt.

ik ga is rondsnuffelen...

Na wat denken, als je een trigger aanmaakt dan kan je toch zelf aangeven tijdens welke actie hij uitgevoerd moet worden. Dan maak je je trigger toch zo aan, dat deze alleen tijdens de insert wordt uitgevoerd.

hieronder een voorbeeldje van het maken van een trigger in een interbase 6.0 database
code:
1
2
3
4
5
6
7
SET TERM !! ;
CREATE TRIGGER "SET_EXCEPTION_ID" FOR "EXCEPTIONS"
    BEFORE INSERT AS
    BEGIN
        NEW.EXCEPTION_ID = GEN_ID(EXCEPTIONS_ID_GEN, 1);
    END !!
SET TERM ; !!

[ Voor 96% gewijzigd door 0528973 op 09-07-2003 12:09 ]

Pascal


Verwijderd

Topicstarter
0528973 schreef op 09 July 2003 @ 11:40:
Post die trigger is aub...
Een trigger kan als je hem normaal schrijft toch niet in een oneindige loop geraken?
Ehmz, komt ie:

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
DECLARE
       -- Two records used to get information from the database about the location
       l RECORD;
       ld RECORD;
BEGIN
       -- Check wether some required fields are actually present
       IF NEW.row IS NULL THEN
          RAISE EXCEPTION ''row cannot be null'';
       END IF;
       IF NEW."column" IS NULL THEN
          RAISE EXCEPTION ''column cannot be null'';
       END IF;
       
       -- Get the details of the location
       SELECT INTO l * FROM location WHERE location = NEW.fk_location;
       
       -- When the specified location is in fact a stack
       IF (l.stack = TRUE) THEN
              -- Get all the CD's that are underneath the new CD
              FOR ld IN SELECT * FROM locationdetails WHERE fk_location = NEW.fk_location AND "column" = NEW."column" AND row >= NEW.row LOOP
                  -- And update them, settings the row one down
                  UPDATE locationdetails SET row = ld.row + 1 WHERE fk_cd = ld.fk_cd AND fk_location = ld.fk_location;
              END LOOP;
       END IF;
       
       -- Return the new item
       RETURN NEW;
END;

  • 0528973
  • Registratie: Juni 2003
  • Laatst online: 15-05-2013
Zie mijn vorige reply :)

Pascal


Verwijderd

Topicstarter
Tjah, maar de trigger moet ook uitgevoerd worden als er een update uitgevoerd wordt ;). Maar dan dus alleen voor de geupdate row, en niet voor alle rows die geupdate worden door de trigger.

  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Volgens mij zoek je een statement trigger, wat je nu hebt is waarschijnlijk een row trigger.
Ik weet niet zeker of postgres dit ondersteund trouwens.

Who is John Galt?


  • 0528973
  • Registratie: Juni 2003
  • Laatst online: 15-05-2013
Het verschil tussen een update via een trigger of via een sql opdracht van je app. is er toch niet? Dus lijkt mij niet dat wat jij wilt gaat lukken op die manier. Misschien dat je een losse update trigger kan maken, welke controleert op een bepaalde variabele in je query.

Je moet dus zelf duidelijk maken om wat voor soort update het gaat, gaat het om een update vanuit de trigger of om een update vanuit je app. Dan kan je in je update trigger controleren waar de update vandaan komt en beslissen wat er gedaan moet worden. Een andere methode is er "dacht" ik niet.

Pascal


Verwijderd

Topicstarter
Ehmz, dit is de DDL van m'n trigger:

SQL:
1
2
3
CREATE TRIGGER "trigger_locationdetails_insert" BEFORE INSERT OR UPDATE 
ON "public"."locationdetails" FOR EACH ROW 
EXECUTE PROCEDURE "public"."movecdsdown"();


Zoals je ziet staat er FOR EACH ROW, dat zou misschien FOR EACH STATEMENT kunnen worden, maar dat wee'k niet zeker. Maar is dat wel de oplossing. Want je zou verwachten dat hij bij FOR EACH ROW voor elke rij die geupdate wordt in 't statement de query uit voert, en bij FOR EACH STATEMENT maar 1 keer bij het uitvoeren. Maar volgens mij staat de code van de trigger daar weer helemaal buiten.

Verwijderd

Topicstarter
0528973 schreef op 09 July 2003 @ 12:47:
Het verschil tussen een update via een trigger of via een sql opdracht van je app. is er toch niet? Dus lijkt mij niet dat wat jij wilt gaat lukken op die manier. Misschien dat je een losse update trigger kan maken, welke controleert op een bepaalde variabele in je query.

Je moet dus zelf duidelijk maken om wat voor soort update het gaat, gaat het om een update vanuit de trigger of om een update vanuit je app. Dan kan je in je update trigger controleren waar de update vandaan komt en beslissen wat er gedaan moet worden. Een andere methode is er "dacht" ik niet.
Wat ik eventueel zou kunnen doen is kijken of OLD.row en NEW.row een verschil hebben van 1. Als dat namelijk zo is is er een kans dat het een update is vanuit m'n trigger. Maar zoals je al wel ziet is dat niet helemaal waterdicht. Dus dan moet ik op de één of andere manier een variable in 't geheugen in stellen terwijl m'n trigger loopt, maar kan dat?

  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Verwijderd schreef op 09 juli 2003 @ 12:50:
Zoals je ziet staat er FOR EACH ROW, dat zou misschien FOR EACH STATEMENT kunnen worden, maar dat wee'k niet zeker. Maar is dat wel de oplossing. Want je zou verwachten dat hij bij FOR EACH ROW voor elke rij die geupdate wordt in 't statement de query uit voert, en bij FOR EACH STATEMENT maar 1 keer bij het uitvoeren. Maar volgens mij staat de code van de trigger daar weer helemaal buiten.
Daar zit hem de clou inderdaad.
Je hebt te maken met een zogenaamd "mutating table" probleem.
De oplossing daarvoor ligt in een row en een statement trigger.
De row trigger verzamelt de pk's/rowids van de ge-update rijen en de statement trigger werkt de tabel bij aan de hand van de verzamelde rijen.

Misschien kun je wel een algemene procedure bedenken die in een keer alle posities bijwerkt, dan kun je het met een statement trigger af.

[ Voor 3% gewijzigd door justmental op 09-07-2003 15:14 ]

Who is John Galt?

Pagina: 1