Home Explore Blog CI



postgresql

56th chunk of `doc/src/sgml/plpgsql.sgml`
406ce2addee81abeeb1e6e130e9db0be0c13be50ef6d6b450000000100000fa4
 <literal>AFTER</literal> or a statement-level trigger
    fired <literal>BEFORE</literal> or <literal>AFTER</literal> is
    always ignored; it might as well be null. However, any of these types of
    triggers might still abort the entire operation by raising an error.
   </para>

   <para>
    <xref linkend="plpgsql-trigger-example"/> shows an example of a
    trigger function in <application>PL/pgSQL</application>.
   </para>

   <example id="plpgsql-trigger-example">
    <title>A <application>PL/pgSQL</application> Trigger Function</title>

    <para>
     This example trigger ensures that any time a row is inserted or updated
     in the table, the current user name and time are stamped into the
     row. And it checks that an employee's name is given and that the
     salary is a positive value.
    </para>

<programlisting>
CREATE TABLE emp (
    empname           text,
    salary            integer,
    last_date         timestamp,
    last_user         text
);

CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
    BEGIN
        -- Check that empname and salary are given
        IF NEW.empname IS NULL THEN
            RAISE EXCEPTION 'empname cannot be null';
        END IF;
        IF NEW.salary IS NULL THEN
            RAISE EXCEPTION '% cannot have null salary', NEW.empname;
        END IF;

        -- Who works for us when they must pay for it?
        IF NEW.salary &lt; 0 THEN
            RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
        END IF;

        -- Remember who changed the payroll when
        NEW.last_date := current_timestamp;
        NEW.last_user := current_user;
        RETURN NEW;
    END;
$emp_stamp$ LANGUAGE plpgsql;

CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE FUNCTION emp_stamp();
</programlisting>
   </example>

   <para>
    Another way to log changes to a table involves creating a new table that
    holds a row for each insert, update, or delete that occurs. This approach
    can be thought of as auditing changes to a table.
    <xref linkend="plpgsql-trigger-audit-example"/> shows an example of an
    audit trigger function in <application>PL/pgSQL</application>.
   </para>

   <example id="plpgsql-trigger-audit-example">
    <title>A <application>PL/pgSQL</application> Trigger Function for Auditing</title>

    <para>
     This example trigger ensures that any insert, update or delete of a row
     in the <literal>emp</literal> table is recorded (i.e., audited) in the <literal>emp_audit</literal> table.
     The current time and user name are stamped into the row, together with
     the type of operation performed on it.
    </para>

<programlisting>
CREATE TABLE emp (
    empname           text NOT NULL,
    salary            integer
);

CREATE TABLE emp_audit(
    operation         char(1)   NOT NULL,
    stamp             timestamp NOT NULL,
    userid            text      NOT NULL,
    empname           text      NOT NULL,
    salary            integer
);

CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$
    BEGIN
        --
        -- Create a row in emp_audit to reflect the operation performed on emp,
        -- making use of the special variable TG_OP to work out the operation.
        --
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO emp_audit SELECT 'D', now(), current_user, OLD.*;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO emp_audit SELECT 'U', now(), current_user, NEW.*;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO emp_audit SELECT 'I', now(), current_user, NEW.*;
        END IF;
        RETURN NULL; -- result is ignored since this is an AFTER trigger
    END;
$emp_audit$ LANGUAGE plpgsql;

CREATE TRIGGER emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
    FOR EACH ROW EXECUTE FUNCTION process_emp_audit();
</programlisting>
   </example>

   <para>
    A variation of the previous example uses a view joining the main table
    to the audit

Title: PL/pgSQL Trigger Examples: Timestamping and Auditing
Summary
This section provides examples of PL/pgSQL trigger functions. The first example demonstrates how to automatically stamp the current user and time into a table row upon insertion or update, also validating employee name and salary. The second shows how to audit changes to a table by logging each insert, update, or delete operation into a separate audit table, recording the operation type, timestamp, and user.