Triggers are special types of stored procedures that automatically execute in response to specific events on a particular table or view in a database. Triggers allow you to define automated actions that occur whenever data is modified, enabling you to enforce business rules, validate data, or maintain audit trails.

Setup

Set up a local cluster

If a local universe is currently running, first destroy it.

Start a local one-node universe with an RF of 1 by first creating a single node, as follows:

./bin/yugabyted start \
                --advertise_address=127.0.0.1 \
                --base_dir=${HOME}/var/node1 \
                --cloud_location=aws.us-east-2.us-east-2a

After starting the yugabyted processes on all the nodes, configure the data placement constraint of the universe, as follows:

./bin/yugabyted configure data_placement --base_dir=${HOME}/var/node1 --fault_tolerance=zone

This command can be executed on any node where you already started YugabyteDB.

To check the status of a running multi-node universe, run the following command:

./bin/yugabyted status --base_dir=${HOME}/var/node1

Setup

To set up a universe, refer to Set up a YugabyteDB Anywhere universe.

Setup

To set up a cluster, refer to Set up a YugabyteDB Aeon cluster.

Create triggers

Creating a trigger in SQL involves defining an automatic action that is executed in response to specified events on a table, such as INSERT, UPDATE, or DELETE. Triggers are created using the CREATE TRIGGER statement, where you specify the event, timing (before or after the event), and the action to be performed.

The CREATE FUNCTION statement has the following syntax:

CREATE FUNCTION trigger_function()
RETURNS TRIGGER LANGUAGE PLPGSQL
AS $$
BEGIN
   -- ...
END;
$$

trigger_function obtains information about the environment that is invoking it via a container populated with local variables.

The CREATE TRIGGER statement has the following syntax:

CREATE TRIGGER tr_name
{BEFORE | AFTER} { event }
ON tbl_name [FOR [EACH] { ROW | STATEMENT }]
       EXECUTE PROCEDURE trigger_function

The trigger tr_name fires before or after event which can be set to INSERT, DELETE, UPDATE, or TRUNCATE. tbl_name represents the table associated with the trigger. If you use the FOR EACH ROW clause, the scope of the trigger would be one row. If you use the FOR EACH STATEMENT clause, the trigger would be fired for each statement. trigger_function represents the procedure to be performed when the trigger is fired.

Example

Suppose you work with a database that includes the following table populated with data:

CREATE TABLE employees (
  employee_no integer PRIMARY KEY,
  name text,
  department text
);
INSERT INTO employees VALUES
(1221, 'John Smith', 'Marketing'),
(1222, 'Bette Davis', 'Sales'),
(1223, 'Lucille Ball', 'Operations'),
(1224, 'John Zimmerman', 'Sales');

If an employee is transferred to a different department, the change is recorded in a table called employee_dept_changes, as shown in the following example:

CREATE TABLE employee_dept_changes (
  employee_no integer NOT NULL,
  name text,
  department text,
  changed_on TIMESTAMP(6) NOT NULL
);

To start recording changes, you create a function called record_dept_changes, as shown in the following example:

CREATE OR REPLACE FUNCTION record_dept_changes()
RETURNS TRIGGER AS
$$
BEGIN
IF NEW.department <> OLD.department
THEN INSERT INTO employee_dept_changes(employee_no, name, department, changed_on)
VALUES(OLD.employee_no, OLD.name, OLD.department, now());
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

The preceding function inserts the old department along with the rest of the employee data into the employee_dept_changes table and adds the time of change if the employee's department changes.

The following example demonstrates how to bind the trigger function to the employees table:

CREATE TRIGGER dept_changes
  BEFORE UPDATE ON employees
  FOR EACH ROW
  EXECUTE PROCEDURE record_dept_changes();

The trigger name in the preceding example is dept_changes. The trigger function is automatically invoked before the value of the department column is updated.

The following example updates the department for one of the employees from the employees table from Sales to Marketing:

UPDATE employees
SET department = 'Marketing'
WHERE employee_no = 1222;

The following is the output produced by the preceding example:

employee_no | name                | department
------------+---------------------+------------------
1221        | John Smith          | Marketing
1222        | Bette Davis         | Marketing
1223        | Lucille Ball        | Operations
1224        | John Zimmerman      | Sales

The following example retrieves all data from the employee_dept_changes table:

SELECT * FROM employee_dept_changes;

The following is the output produced by the preceding example:

employee_no | name            | department   | changed_on
------------+-----------------+--------------+----------------------------
1222        | Bette Davis     | Sales        | 2021-02-11 16:12:09.248823

The employee_dept_changes table is populated with a row containing the employee whose department has changed, as well as the date and time of the change.

Delete triggers

The DROP TRIGGER statement allows you to delete the trigger from a table.

The DROP TRIGGER statement has the following syntax:

DROP TRIGGER [IF EXISTS] tr_name
  ON tbl_name [ CASCADE | RESTRICT ];

tr_name represents the trigger to be deleted if it exists. If you try to delete a non-existing trigger without using the IF EXISTS statement, the DROP TRIGGER statement results in an error, whereas using IF EXISTS to delete a non-existing trigger results in a notice. tbl_name represents the table associated with the trigger. The CASCADE option allows you to automatically delete objects that depend on the trigger and the RESTRICT option (default) allows you to refuse to delete the trigger if it has dependent objects.

Example

The following example demonstrates how to delete the dept_changes trigger used in the examples from Create triggers:

DROP TRIGGER dept_changes ON employees;

Enable and Disable triggers

You can disable one or more triggers associated with a table via the ALTER TABLE DISABLE TRIGGER statement that has the following syntax:

ALTER TABLE tbl_name
  DISABLE TRIGGER tr_name |  ALL;

tbl_name represents the table whose trigger represented by tr_name you are disabling. Using the ALL option allows you to disable all triggers associated with the table. A disabled trigger, even though it exists in the database, cannot fire on an event associated with this trigger.

Examples

The following example shows how to disable a trigger on the employees table:

ALTER TABLE employees
  DISABLE TRIGGER dept_changes;

The following example shows how to disable all triggers associated with the employees table:

ALTER TABLE employees
  DISABLE TRIGGER ALL;

You can enable one or more previously disabled triggers associated with a table via the ALTER TABLE ENABLE TRIGGER statement that has the following syntax:

ALTER TABLE tbl_name
  ENABLE TRIGGER tr_name |  ALL;

tbl_name represents the table whose trigger represented by tr_name you are enabling. Using the ALL option allows you to enable all triggers associated with the table.

The following example shows how to enable a trigger on the employees table:

ALTER TABLE employees
  ENABLE TRIGGER dept_changes;

The following example shows how to enable all triggers associated with the employees table:

ALTER TABLE employees
  ENABLE TRIGGER ALL;

Event triggers

The main difference between regular triggers and event triggers is that the former capture data manipulation events on a single table, whereas the latter can capture data definition events on a database.

The CREATE EVENT TRIGGER statement has the following syntax:

CREATE EVENT TRIGGER tr_name ON event
  [ WHEN filter_variable IN (filter_value [, ... ]) [ AND ... ] ]
  EXECUTE PROCEDURE function_name();

tr_name, which is unique in the database, represents the new trigger. event represents the event that triggers a call to the function function_name whose return type is event_trigger (optional). You can define more than one trigger for the same event, in which case the triggers fire in alphabetical order based on the name of the trigger. If a WHEN condition is included in the CREATE EVENT TRIGGER statement, then the trigger is fired for specific commands. filter_variable needs to be set to TAG, as this is the only supported variable, and filter_value represents a list of values for filter_variable.

Example

The following example is based on examples from Create triggers, except that the record_dept_changes function returns an event trigger instead of a regular trigger. The example shows how to create an sql_drop trigger for one of the events currently supported by YSQL:

CREATE OR REPLACE FUNCTION record_dept_changes()
RETURNS EVENT_TRIGGER AS
$$
BEGIN
IF NEW.department <> OLD.department
THEN INSERT INTO employee_dept_changes(employee_no, name, department, changed_on)
VALUES(OLD.employee_no, OLD.name, OLD.department, now());
END IF;
END;
$$
LANGUAGE 'plpgsql';
CREATE EVENT TRIGGER dept_changes ON sql_drop
  EXECUTE PROCEDURE record_dept_changes();