Beginner-friendly notes on PostgreSQL database triggers with practical dvdrental examples.
A trigger is a special database object that automatically runs before or after an event on a table.
A trigger has two parts:
A PL/pgSQL function containing the logic.
Defines when and on which table the function should run.
| Type | Runs When |
|---|---|
| BEFORE | Before the row is inserted/updated/deleted |
| AFTER | After the row action completes |
| Event | Meaning |
|---|---|
| INSERT | When new row is added |
| UPDATE | When existing row changes |
| DELETE | When row is removed |
| Type | Meaning |
|---|---|
| ROW | Runs once per affected row |
| STATEMENT | Runs once per SQL statement |
CREATE OR REPLACE FUNCTION update_film_timestamp()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.last_update := NOW(); -- change the last_update column
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_update_film_timestamp
BEFORE UPDATE ON film
FOR EACH ROW
EXECUTE FUNCTION update_film_timestamp();
Whenever you update a film’s title, rating, rental rate, etc., the last_update column automatically updates.
CREATE TABLE rental_log (
rental_id INT,
customer_id INT,
rental_date TIMESTAMP,
action_time TIMESTAMP DEFAULT NOW()
);
CREATE OR REPLACE FUNCTION log_rental_delete()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO rental_log(rental_id, customer_id, rental_date)
VALUES (OLD.rental_id, OLD.customer_id, OLD.rental_date);
RETURN OLD;
END;
$$;
CREATE TRIGGER trg_log_rental_delete
AFTER DELETE ON rental
FOR EACH ROW
EXECUTE FUNCTION log_rental_delete();
Whenever a rental row is deleted, it is recorded in rental_log.
CREATE OR REPLACE FUNCTION validate_customer_email()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.email IS NULL OR NEW.email = '' THEN
RAISE EXCEPTION 'Email cannot be empty!';
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_validate_customer_email
BEFORE INSERT ON customer
FOR EACH ROW
EXECUTE FUNCTION validate_customer_email();
The database prevents incomplete customer records.
CREATE OR REPLACE FUNCTION notify_new_customer()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
RAISE NOTICE 'New customer added: % %', NEW.first_name, NEW.last_name;
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_notify_new_customer
AFTER INSERT ON customer
FOR EACH ROW
EXECUTE FUNCTION notify_new_customer();
CREATE OR REPLACE FUNCTION validate_payment_amount()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.amount <= 0 THEN
RAISE EXCEPTION 'Payment amount must be greater than zero';
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_validate_payment_amount
BEFORE INSERT OR UPDATE ON payment
FOR EACH ROW
EXECUTE FUNCTION validate_payment_amount();
| Concept | Meaning |
|---|---|
| Trigger | Auto-runs on INSERT/UPDATE/DELETE |
| Trigger Function | Contains logic in PL/pgSQL |
| BEFORE Trigger | Validates/changes data before save |
| AFTER Trigger | Used for logs, history, messages |
| NEW | The new row after insert/update |
| OLD | The old row before update/delete |
| FOR EACH ROW | Runs once per affected row |