This feature is in and subject to change. To share feedback and/or issues, contact Support.
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
BEFOREorAFTERany combination ofINSERT,UPDATE, orDELETEstatements is issued on a given table.FOR EACH ROWspecifies a row-level trigger, which activates once for each row that is affected by the statements.WHENspecifies 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 theOR 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.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.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:- All
BEFOREtriggers activate before allAFTERtriggers. BEFORE INSERTtriggers activate beforeBEFORE UPDATEtriggers.- The triggers activate in alphabetical order by trigger name.
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
BEFOREtrigger must return one of the following values:- The
NEWtable row resulting from the SQL operation that activated the trigger. This variable applies only toINSERTandUPDATEtriggers, and also allows theBEFOREtrigger to modify the row before it is written. - The
OLDtable row affected by the SQL operation that activated the trigger. This variable applies only toUPDATEandDELETEtriggers. NULL, which stops the SQL operation that activated theBEFOREtrigger.
- The
- The function for an
AFTERtrigger typically returnsNULLby convention, because its return value will be ignored. - The function must be defined before creating the trigger.
Trigger variables
The following trigger variables are automatically created for trigger functions, and can be used in the function body.| Variable | Type | Description |
|---|---|---|
NEW | RECORD | New 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. |
OLD | RECORD | Old 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_NAME | NAME | Name of the trigger that was activated. |
TG_WHEN | STRING | When the trigger is set to activate: BEFORE or AFTER. |
TG_LEVEL | STRING | Scope of trigger behavior: ROW. |
TG_OP | STRING | SQL operation that activated the trigger: INSERT, UPDATE, or DELETE. |
TG_RELID | OID | of the table associated with the trigger. |
TG_TABLE_NAME | NAME | Name of the table associated with the trigger. |
TB_TABLE_SCHEMA | NAME | Name of the table schema associated with the trigger. |
TG_NARGS | INT | Number of arguments passed to the trigger function in the definition. |
TG_ARGV | STRING[] | 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.-
Run to start a temporary, in-memory cluster with the sample dataset preloaded:
-
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:
-
Create a that inserts the corresponding values into the
audit_logtable:This function inserts the following trigger variables:TG_TABLE_NAME: The table associated with the trigger. In this example, this will beusers.TG_OP: The SQL operation that was performed on the table, thus activating the trigger.OLD: The old table row affected byUPDATEandDELETEoperations.NEW: The new table row resulting fromINSERTandUPDATEoperations.
current_timestampgenerates a new timestamp each time the function is executed by the trigger. -
Create a trigger that executes the
audit_changesfunction after anINSERT,UPDATE, orDELETEis issued on theuserstable:
-
Test the trigger by inserting, updating, and deleting a row in the
userstable of themovrdatabase:The trigger activates after each of the preceding 3 statements. -
View the results in the
audit_logtable:BecauseOLDdoes not apply toINSERToperations, andNEWdoes not apply toDELETEoperations, their correspondingold_dataandnew_datavalues areNULL, 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”.-
Create the following two sample tables.
productscontains a list of products, andorderscontains a list of orders on those products: -
Create a
product_sales_summarytable that stores summary records. Each record includes the total number of orders and the total value of sales for each product: -
Create a that updates existing summary records, or inserts a new summary record, to reflect each order that is placed:
(NEW).quantity * (NEW).priceis the total value of each new order. This value is aggregated into thetotal_salesvalue in theproduct_sales_summarytable. -
Create a trigger that executes the
update_product_sales_summaryfunction after anINSERTis issued on theorderstable (i.e., an order is placed):Because this trigger executes theupdate_product_sales_summaryfunction 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 theorderstable (e.g.,SUM(quantity * price)). -
Set up the example scenario by inserting two sample product names and creating a function to randomly generate orders on those product names:
-
Run the example function, generating 100 orders:
-
View some of the orders that were generated:
-
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.
-
Create a sample table of employees and their wages:
-
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
NEWrow resulting from the SQL operation. -
Create a trigger that executes the
ensure_minimum_wagefunction before anINSERTorUPDATEis issued on theemployeestable: -
Create a trigger function that adds an initial starting bonus of
5to each new wage: -
Create a trigger that executes the
give_bonusfunction before anINSERTorUPDATEis issued on theemployeestable:Bothtrg_ensure_minimum_wageandtrg_give_bonusareBEFOREtriggers that activate before anyINSERTorUPDATEis issued onemployees. Becausetrg_give_bonuscomes alphabetically aftertrg_ensure_minimum_wage, it activates second. For details on this behavior, refer to Trigger conditions. -
Create a trigger function that prints an employee’s final wage with the bonus applied.
-
Create a trigger that executes the
print_final_wagefunction after anINSERTorUPDATEis issued on theemployeestable:ThisAFTERtrigger activates after the SQL operation and bothBEFOREtriggers are written toemployees, ensuring that it prints the final value of the row. -
Test the triggers by adding a new employee with a wage of
20:This output demonstrates the following order of events:trg_ensure_minimum_wageactivates beforetrg_give_bonus, so the “Starting wage” message is printed before the “Modifying wage” message.trg_give_bonusreceives theNEWrow value (20.00) returned bytrg_ensure_minimum_wage, which is unmodified from theINSERToperation. After printing the “Modifying wage” message, the function adds5to the row value and returns a modifiedNEWvalue.- The
NEWvalue is written to the row. trg_print_final_wageprints the “Final wage” message with the committed row value (25.00).
-
Add a new employee with a wage of
10:This output demonstrates the following order of events:trg_ensure_minimum_wageprints the “Starting wage” message.- The row value fails the conditional check in
ensure_minimum_wage, and raises an exception. - The
ERRORmessage is printed and the SQL operation is aborted before thegive_bonusfunction is executed.
Video demo
For a deep-dive demo on triggers, play the following video:Known limitations
CREATE OR REPLACE TRIGGERis not supported.- Statement-level triggers are not supported.
INSTEAD OFtriggers are not supported.- A that is used in an existing trigger cannot be replaced with
CREATE OR REPLACEsyntax. To useCREATE OR REPLACE, first that are using the function. - Hidden columns are not visible to triggers.
- with
CASCADEis not supported.

