Skip to main content
Documents
Basic SyntaxMath FunctionsDate FunctionsJSON FunctionsDatabasesTables & Schema ManagementString FunctionsTriggersIndexes

PostgreSQL Row-level Triggers

Triggers in PostgreSQL are procedures that are automatically executed in response to certain events on a particular table or view. Row-level triggers are specifically executed for each row affected by an event such as an `INSERT`, `UPDATE`, or `DELETE`.

Usage

Row-level triggers are utilized to enforce business rules, validate data, or maintain custom logging at the row level. They are defined to perform specific actions whenever a row is modified in a specified manner.

sql
CREATE TRIGGER trigger_name
AFTER | BEFORE INSERT | UPDATE | DELETE
ON table_name
FOR EACH ROW
EXECUTE FUNCTION function_name();

In this syntax, `FOR EACH ROW` specifies that the trigger will fire for each affected row, and `EXECUTE FUNCTION` calls the function that contains the logic to be executed.

Examples

1. Basic Insert Trigger

sql
CREATE OR REPLACE FUNCTION log_new_inserts()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO audit_log (table_name, operation, timestamp)
  VALUES (TG_TABLE_NAME, 'INSERT', now());
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER log_insert
AFTER INSERT ON employees
FOR EACH ROW
EXECUTE FUNCTION log_new_inserts();

This example creates a trigger that logs every new `INSERT` operation on the `employees` table to an `audit_log` table.

2. Update Trigger with Condition

sql
CREATE OR REPLACE FUNCTION check_salary_update()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.salary < OLD.salary THEN
    RAISE EXCEPTION 'Salary cannot be decreased!';
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER salary_check
BEFORE UPDATE ON employees
FOR EACH ROW
EXECUTE FUNCTION check_salary_update();

Here, a trigger prevents salary reductions by raising an exception if the new salary is less than the old one during an `UPDATE`.

3. Delete Trigger with Logging

sql
CREATE OR REPLACE FUNCTION log_delete()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO delete_log (table_name, deleted_row_id, timestamp)
  VALUES (TG_TABLE_NAME, OLD.id, now());
  RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER log_delete
AFTER DELETE ON orders
FOR EACH ROW
EXECUTE FUNCTION log_delete();

This example logs details of deleted rows from the `orders` table into a `delete_log` for audit purposes. It assumes `OLD.id` corresponds to the primary key or a unique identifier of the row.

Tips and Best Practices

  • Use triggers judiciously. Overusing triggers may lead to complex and hard-to-debug systems.
  • Ensure atomicity. The trigger function should be atomic and idempotent to maintain data integrity.
  • Consider performance impacts. Triggers add overhead and are executed synchronously with the triggering operation; ensure they are optimized for performance to avoid slowing down database operations.
  • Test triggers thoroughly. Ensure comprehensive testing to validate that triggers behave correctly under all scenarios.
  • Document trigger logic. Clearly document the purpose and logic of each trigger for future reference and maintenance.

Additional Information

Special Variables: PostgreSQL triggers use special variables like `TG_TABLE_NAME`, `NEW`, and `OLD` to provide context. `TG_TABLE_NAME` refers to the name of the table the trigger is associated with, `NEW` holds the new row data for `INSERT` or `UPDATE` operations, and `OLD` holds the existing row data for `UPDATE` or `DELETE` operations.