Subject | Re: How to avoid Triggers' infinite loop? |
---|---|
Author | Adam |
Post date | 2005-08-31T00:15:12Z |
> multiple registries in tableB and tableB updates only one registryat a
> time in tableA ?..Hello Anderson,
>
> Like this:
>
> TABLE_A
> FIELD1_KEY
> DATAFIELD
>
> TABLE_B
> FIELD1_KEY
> FIELD2_FKEY (References TABLE_A.FIELD1_KEY)
> DATAFIELD
>
You will go mad if you don't realise that there is nothing different
between cascading triggers and any other recursive algorithm. All you
need to do is ensure there is a always an exit condition and it will
work. The only reason you are having troubles is that one is updating
the other which is updating the first one again which is updating the
other again infinitum (or until you run out of stack).
Now let me look at your example.
TABLE_A
FIELD1_KEY
DATAFIELD
TABLE_B
FIELD1_KEY
FIELD2_FKEY (References TABLE_A.FIELD1_KEY)
DATAFIELD
I assume you want to do something like keep the datafield the same
(in which case I would question what DataField is doing in TableB to
start with, it should only be in tableA and you can join to it if you
need it in tableB).
But assuming you have a good answer for that, or that this is
incredibly oversimplified and perhaps doesn't exactly represent your
problem, the exit condition is pretty easy.
tableA_au trigger
IF OLD.DATAFIELD <> NEW.DATAFIELD THEN
BEGIN
UPDATE TABLE_B
SET DATAFIELD = NEW.DATAFIELD
WHERE FIELD2_KEY = NEW.FIELD1_KEY
AND DATAFIELD <> NEW.DATAFIELD;
END
Do the reverse for the tableB trigger
There are two things here.
Firstly, the update doesn't fire if it is not interesting to the
other table. (If the value of interest hasn't been modified, who
cares about the update).
Secondly, the update statement itself does not change the record if
the set operation would have done nothing anyway, so the trigger on
tableB would not be fired.
Hope that helps
Adam.