Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make a trigger to update a column in another table?

So I am working on adding a last updated time to the database for my app's server. The idea is that it will record the time an update is applied to one of our trips and then the app can send a get request to figure out if it's got all of the correct up to date information.

I've added the column to our table, and provided the service for it all, and finally manage to get a trigger going to update the column every time a change is made to a trip in it's trip table. My problem now comes from the fact that the information that pertains to a trip is stored across a multitude of other tables as well (for instance, there are tables for the routes that make up a trip and the photos that a user can see on the trip, etc...) and if any of that data changes, then the trip's update time also needs to change. I can't for the life of me figure out how to set up the trigger so that when I change some route information, the last updated time for the trip(s) the route belongs to will be updated in it's table.

This is my trigger code as it stands now: it updates the trip table's last updated column when that trip's row is updated.

CREATE OR REPLACE FUNCTION record_update_time() RETURNS TRIGGER AS
    $$
        BEGIN
            NEW.last_updated=now();
            RETURN NEW;
        END;
    $$ 
    LANGUAGE PLPGSQL;

CREATE TRIGGER update_entry_on_entry_change
    BEFORE UPDATE ON mydatabase.trip FOR EACH ROW
    EXECUTE PROCEDURE record_update_time();

--I used the next two queries just to test that the trigger works. It
--probably doesn't make a difference to you but I'll keep it here for reference
UPDATE mydatabase.trip
    SET title='Sample New Title'
    WHERE id = 2;
SELECT *
    FROM mydatabase.trip
    WHERE mydatabase.trip.id < 5;

Now I need it to update when the rows referencing the trip row with a foreign key get updated. Any ideas from someone more experienced with SQL triggers than I?

like image 690
cbhedd Avatar asked Oct 20 '22 07:10

cbhedd


1 Answers

"mydatabase" is a remarkably unfortunate name for a schema.

The trigger function could look like this:

CREATE OR REPLACE FUNCTION trg_upaft_upd_trip()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   UPDATE mydatabase.trip t    -- "mydatabase" = schema name (?!)
   SET    last_updated = now()
   WHERE  t.id = NEW.trip_id   -- guessing column names      

   RETURN NULL;                -- calling this AFTER UPDATE
END
$func$;

And needs to be used in a trigger on every related table (not on trip itself):

CREATE TRIGGER upaft_upd_trip
AFTER UPDATE ON mydatabase.trip_detail
FOR EACH ROW EXECUTE PROCEDURE trg_upaft_upd_trip();

You also need to cover INSERT and DELETE (and possibly COPY) on all sub-tables ...

This approach has many potential points of failure. As alternative, consider a query or view that computes the latest last_updated from sub-tables dynamically. If you update often this might be the superior approach.
If you rarely UPDATE and SELECT often, your first approach might pay.

like image 187
Erwin Brandstetter Avatar answered Oct 23 '22 03:10

Erwin Brandstetter