Skip to main content
A trigger executes a function when one or more specified SQL operations is performed on a table. The executed function is called a trigger function and is written in . Triggers respond to data changes by adding logic within the database, rather than in an application. They can be used to modify data before it is inserted, maintain data consistency across rows or tables, or record an update to a row.

Structure

A trigger consists of a trigger name, table name associated with the trigger, SQL operations and other conditions that activate the trigger, and a trigger function name with optional arguments. A trigger is defined with and has the following overall structure:
  • The trigger can activate BEFORE or AFTER any combination of INSERT, UPDATE, or DELETE statements is issued on a given table.
    • FOR EACH ROW specifies a row-level trigger, which activates once for each row that is affected by the statements.
    • WHEN specifies an optional boolean condition that determines whether the trigger activates for a given row.
    • For details on the preceding behaviors, refer to Trigger conditions.
  • The trigger function, written in , is executed each time the trigger activates. A comma-separated list of constant string arguments can be included.

Trigger conditions

A trigger activates when one or more SQL statements is issued on a table. The statement can be , , or . To specify more than one statement, use the OR clause. For example:
INSERT and UPDATE triggers activate when statements insert or update rows, respectively. However, UPSERT cannot be specified in a statement.UPDATE triggers activate when the clause of an INSERT updates rows.
If BEFORE is specified, the trigger activates before the SQL operation. BEFORE triggers can be used to validate or modify data before it is inserted, or to check row values before they are updated. If AFTER is specified, the trigger activates after the SQL operation commits. AFTER triggers can be used to audit or cascade changes to other tables, thus maintaining data consistency. The FOR EACH ROW clause must be included after the table name. This specifies a row-level trigger that activates once for each table row that is affected by the SQL operations. An optional WHEN boolean condition can then be added. This further controls whether the trigger activates on an affected row, and is typically applied to the OLD or NEW trigger variables. For example, the following trigger only activates if the row’s address value was changed by the UPDATE:
Due to a , OLD and NEW must be wrapped in parentheses when accessing column names.
Only OLD can be referenced in the WHEN clause of a DELETE trigger, and only NEW in the WHEN clause of an INSERT trigger. OLD or NEW or both can be referenced in the WHEN clause of an UPDATE trigger. For details, refer to Trigger variables.

Trigger ordering

When multiple triggers activate on the same table, the order is determined as follows:
  1. All BEFORE triggers activate before all AFTER triggers.
  2. BEFORE INSERT triggers activate before BEFORE UPDATE triggers.
  3. The triggers activate in alphabetical order by trigger name.
The output of a BEFORE trigger is passed to the next BEFORE trigger. For details on values returned by triggers, refer to Trigger function. For an example, refer to Demonstrate BEFORE and AFTER trigger ordering.

Trigger function

A trigger executes a called a trigger function. A trigger function is defined with and has the following requirements:
  • The function must return type TRIGGER.
  • The function must be declared without arguments.
  • The function must be written in .
  • The function for a BEFORE trigger must return one of the following values:
    • The NEW table row resulting from the SQL operation that activated the trigger. This variable applies only to INSERT and UPDATE triggers, and also allows the BEFORE trigger to modify the row before it is written.
    • The OLD table row affected by the SQL operation that activated the trigger. This variable applies only to UPDATE and DELETE triggers.
    • NULL, which stops the SQL operation that activated the BEFORE trigger.
  • The function for an AFTER trigger typically returns NULL by convention, because its return value will be ignored.
  • The function must be defined before creating the trigger.
Refer to Examples.

Trigger variables

The following trigger variables are automatically created for trigger functions, and can be used in the function body.
VariableTypeDescription
NEWRECORDNew table row resulting from the SQL operation. For INSERT triggers, this is the row that will be inserted. For UPDATE triggers, this is the row containing the updated values. For DELETE triggers, this is NULL.
OLDRECORDOld table row affected by UPDATE and DELETE operations. For UPDATE triggers, this is the row that will be updated. For DELETE triggers, this is the row that will be deleted. For INSERT triggers, this is NULL.
TG_NAMENAMEName of the trigger that was activated.
TG_WHENSTRINGWhen the trigger is set to activate: BEFORE or AFTER.
TG_LEVELSTRINGScope of trigger behavior: ROW.
TG_OPSTRINGSQL operation that activated the trigger: INSERT, UPDATE, or DELETE.
TG_RELIDOID of the table associated with the trigger.
TG_TABLE_NAMENAMEName of the table associated with the trigger.
TB_TABLE_SCHEMANAMEName of the table schema associated with the trigger.
TG_NARGSINTNumber of arguments passed to the trigger function in the definition.
TG_ARGVSTRING[]Arguments passed to the trigger function in the definition.

Examples

Create an audit log

In the following example, a trigger is used to log data changes to an “audit log” table.
  1. Run to start a temporary, in-memory cluster with the sample dataset preloaded:
  2. Create a table that stores audit records. Each record includes the table that was affected, the SQL operation that was performed on the table, the old and new table rows, and the timestamp when the change was made:
  3. Create a that inserts the corresponding values into the audit_log table:
    This function inserts the following trigger variables:
    • TG_TABLE_NAME: The table associated with the trigger. In this example, this will be users.
    • TG_OP: The SQL operation that was performed on the table, thus activating the trigger.
    • OLD: The old table row affected by UPDATE and DELETE operations.
    • NEW: The new table row resulting from INSERT and UPDATE operations.
    current_timestamp generates a new timestamp each time the function is executed by the trigger.
  4. Create a trigger that executes the audit_changes function after an INSERT, UPDATE, or DELETE is issued on the users table:
The audit_changes function can be used to audit changes on multiple tables. You can create another trigger, on a table name other than users, that also executes audit_changes.
  1. Test the trigger by inserting, updating, and deleting a row in the users table of the movr database:
    The trigger activates after each of the preceding 3 statements.
  2. View the results in the audit_log table:
    Because OLD does not apply to INSERT operations, and NEW does not apply to DELETE operations, their corresponding old_data and new_data values are NULL, respectively. For details, refer to Trigger variables.

Create a summary table

In the following example, a trigger is used to calculate sales figures for a “summary table”.
  1. Create the following two sample tables. products contains a list of products, and orders contains a list of orders on those products:
  2. Create a product_sales_summary table that stores summary records. Each record includes the total number of orders and the total value of sales for each product:
  3. Create a that updates existing summary records, or inserts a new summary record, to reflect each order that is placed:
    (NEW).quantity * (NEW).price is the total value of each new order. This value is aggregated into the total_sales value in the product_sales_summary table.
  4. Create a trigger that executes the update_product_sales_summary function after an INSERT is issued on the orders table (i.e., an order is placed):
    Because this trigger executes the update_product_sales_summary function directly after each row is affected by a SQL operation, it spares you from having to run a potentially expensive query on those values in the orders table (e.g., SUM(quantity * price)).
  5. Set up the example scenario by inserting two sample product names and creating a function to randomly generate orders on those product names:
  6. Run the example function, generating 100 orders:
  7. View some of the orders that were generated:
  8. View the aggregated results on the summary table:

Demonstrate BEFORE and AFTER trigger ordering

In the following example, a combination of BEFORE and AFTER triggers is used to demonstrate the order in which they activate.
  1. Create a sample table of employees and their wages:
  2. Create a that checks whether a new wage is below the minimum:
    The function prints the wage that is initially assigned to the employee. If the new wage is below minimum, the function to abort the SQL operation that changes the wage. Otherwise, it returns the NEW row resulting from the SQL operation.
  3. Create a trigger that executes the ensure_minimum_wage function before an INSERT or UPDATE is issued on the employees table:
  4. Create a trigger function that adds an initial starting bonus of 5 to each new wage:
  5. Create a trigger that executes the give_bonus function before an INSERT or UPDATE is issued on the employees table:
    Both trg_ensure_minimum_wage and trg_give_bonus are BEFORE triggers that activate before any INSERT or UPDATE is issued on employees. Because trg_give_bonus comes alphabetically after trg_ensure_minimum_wage, it activates second. For details on this behavior, refer to Trigger conditions.
  6. Create a trigger function that prints an employee’s final wage with the bonus applied.
  7. Create a trigger that executes the print_final_wage function after an INSERT or UPDATE is issued on the employees table:
    This AFTER trigger activates after the SQL operation and both BEFORE triggers are written to employees, ensuring that it prints the final value of the row.
  8. Test the triggers by adding a new employee with a wage of 20:
    This output demonstrates the following order of events:
    1. trg_ensure_minimum_wage activates before trg_give_bonus, so the “Starting wage” message is printed before the “Modifying wage” message.
    2. trg_give_bonus receives the NEW row value (20.00) returned by trg_ensure_minimum_wage, which is unmodified from the INSERT operation. After printing the “Modifying wage” message, the function adds 5 to the row value and returns a modified NEW value.
    3. The NEW value is written to the row.
    4. trg_print_final_wage prints the “Final wage” message with the committed row value (25.00).
  9. Add a new employee with a wage of 10:
    This output demonstrates the following order of events:
    1. trg_ensure_minimum_wage prints the “Starting wage” message.
    2. The row value fails the conditional check in ensure_minimum_wage, and raises an exception.
    3. The ERROR message is printed and the SQL operation is aborted before the give_bonus function is executed.

Video demo

For a deep-dive demo on triggers, play the following video:

Known limitations

  • Statement-level triggers are not supported.
  • INSTEAD OF triggers are not supported.
  • Hidden columns are not visible to triggers.
  • The REFERENCING clause for CREATE TRIGGER is not supported.
  • UPDATE triggers with a column list (using UPDATE OF column_name syntax) are not supported.
  • Statement-level triggers for TRUNCATE events are not supported.

See also