I wrote a post-update trigger for a form yesterday; the code seemed correct
    when I looked at it, but it didn't work when added to the form. The code
    itself took some data from the form, inserted them into the GENERALLOAD
    table then called an interface in order to do something in another form. I
    extracted the code and rearranged it slightly to become a self-standing
    procedure so that I could debug it; the procedure worked properly. So why
    didn't the trigger work? 
  The answer half came to me when walking the dog at 5:30 am (always a
    productive time for mental debugging): check other triggers for this form to
    see whether they linked the GENERALLOAD table, and more importantly, whether
    they unlinked the table. And of course, I found another post-update trigger
    that I wrote that linked GENERALLOAD but did not unlink it.
  In the context of the form, when the second trigger came to link
    GENERALLOAD, the link failed because the table was already linked. Had I
    been clever enough to display a warning message if the link failed, instead
    of skipping to the end of the trigger, then I would have known immediately
    what the problem was.
  Moral of the story: ALWAYS UNLINK GENERALLOAD at the end of a
    trigger!!
  This isn't as clear cut as one would like to think. Normally one writes
    code such as
EXECUTE INTERFACE 'STATUSMAILQ', SQL.TMPFILE, '-L', :$.G2;
SELECT MESSAGE INTO :PAR1 FROM ERRMSGS                              
WHERE USER = SQL.USER AND TYPE = 'i';                               
ERRMSG 99 WHERE :RETVAL > 0; 
The question is: does ERRMSG cause the linked table (:$.G2 in this case) to be unlinked? I suspect not, so alternative methods have to be found in a trigger - probably using WRNMSG, then unlinking the table, then jumping to the end of the procedure. Or unlinking directly after the 'execute' line and before the 'select' line; this way, RETVAL will hold the result of the SELECT statement.