PostgreSQL has no ON UPDATE CURRENT_TIMESTAMP clause. Schemas ported from MySQL usually keep DEFAULT CURRENT_TIMESTAMP on the updated_at column and expect the value to stay fresh, but in Postgres that default only fires on insert. It does not auto update the row on later writes. Here's the MySQL setup people port over:
CREATE TABLE Users (
...
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);In MySQL that second column re-stamps itself on every UPDATE. In PostgreSQL the same column keeps whatever value it got at insert time.
A trigger is a function Postgres runs automatically when an event happens on a table, such as an insert, an update, or a delete. Triggers are how you enforce business rules, keep audit columns current, or maintain data integrity. They're also the replacement for MySQL's ON UPDATE CURRENT_TIMESTAMP.
Start with the function itself. It sets the updated_at field on the row Postgres is about to write, then returns that row:
CREATE OR REPLACE FUNCTION trigger_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;The function does nothing until a trigger calls it. Attach it to the Users table so it runs before each row is written. The full syntax is in the PostgreSQL CREATE TRIGGER documentation:
CREATE TRIGGER update_users_updated_on
BEFORE UPDATE
ON
Users
FOR EACH ROW
EXECUTE PROCEDURE trigger_updated_at();Now the updated_at column is automatically set to the current timestamp every time a row is modified. Inserts still work as before, because the column default handles those.
Drizzle has no way to declare a Postgres trigger in the schema. Its $onUpdate helper runs in the client and stamps the column on every update the ORM issues:
updatedAt: timestamp('updated_at').defaultNow().$onUpdate(() => new Date()),That covers writes going through Drizzle. Writes from psql, a migration, or another service still need the trigger.
To auto-update a timestamp in PostgreSQL like MySQL's ON UPDATE CURRENT_TIMESTAMP, use a trigger. Create a trigger function to set updated_at to NOW() on updates, then activate it on your table with a BEFORE UPDATE trigger.
Occasional notes on software, tools, and things I learn. No spam.
Unsubscribe anytime.