How to View PostgreSQL Trigger Definition and Details Using psql


11 views

When working with PostgreSQL triggers, you'll often need to inspect their complete definition beyond just listing them. While \dft shows a list of triggers, you need deeper inspection methods.

The most comprehensive way to view trigger details is querying the system catalog:

SELECT tgname AS trigger_name, 
       tgrelid::regclass AS table_name,
       tgenabled AS status,
       tgtype AS events,
       tgfoid::regproc AS function_name,
       tgargs AS function_args
FROM pg_trigger
WHERE tgname = 'your_trigger_name';

The tgtype field contains bitmask values representing trigger events:

-- Common event bitmasks
SELECT 
  (1<<0) AS "INSERT",
  (1<<1) AS "DELETE",
  (1<<2) AS "UPDATE",
  (1<<3) AS "TRUNCATE";

To see the actual function code being executed:

SELECT prosrc 
FROM pg_proc 
WHERE oid = (SELECT tgfoid FROM pg_trigger WHERE tgname = 'your_trigger_name');

For quick inspection, use these psql meta-commands:

\sf+ trigger_function_name  -- Show function definition
\d+ table_name              -- Show table structure including triggers

Let's examine an audit trigger:

-- Create sample trigger
CREATE TRIGGER audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW EXECUTE FUNCTION audit_employee_changes();

-- View its definition
SELECT pg_get_triggerdef(oid) 
FROM pg_trigger 
WHERE tgname = 'audit_trigger';

To save all triggers for a table:

SELECT pg_get_triggerdef(oid) || ';' AS trigger_definition
FROM pg_trigger
WHERE tgrelid = 'your_table_name'::regclass;

When working with PostgreSQL triggers, developers often need to inspect specific trigger definitions beyond what \dft provides. The pg_trigger system catalog contains comprehensive metadata about all triggers in the database.

SELECT tgname, tgtype, tgenabled, tgconstraint, tgdeferrable, tginitdeferred,
       tgconstrrelid::regclass, tgconstrindid::regclass, tgfoid::regproc,
       tgargs, tgqual
FROM pg_trigger
WHERE tgname = 'your_trigger_name';

For a more human-readable format, use the pg_get_triggerdef() function:

SELECT pg_get_triggerdef(oid) AS trigger_definition
FROM pg_trigger
WHERE tgname = 'your_trigger_name';

Let's examine a trigger that logs changes to a products table:

-- First create the example trigger
CREATE OR REPLACE FUNCTION log_product_changes()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO product_audit(product_id, changed_at, old_price, new_price)
    VALUES (OLD.product_id, now(), OLD.price, NEW.price);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER product_price_update_trigger
AFTER UPDATE OF price ON products
FOR EACH ROW
EXECUTE FUNCTION log_product_changes();

Now query its details:

SELECT 
    tgname AS trigger_name,
    tgtype AS trigger_type,
    tgenabled AS is_enabled,
    tgisinternal AS is_internal,
    tgdeferrable AS is_deferrable,
    tginitdeferred AS initially_deferred,
    pg_get_triggerdef(oid) AS trigger_definition
FROM pg_trigger
WHERE tgname = 'product_price_update_trigger';

The tgtype field contains bitmask values indicating trigger characteristics:

-- Common tgtype values:
-- 1: BEFORE
-- 2: AFTER
-- 4: INSTEAD OF
-- 8: ROW-level
-- 16: STATEMENT-level
-- 32: INSERT operation
-- 64: UPDATE operation
-- 128: DELETE operation
-- 256: TRUNCATE operation

For standardized metadata access, query the information_schema.triggers view:

SELECT 
    trigger_name,
    event_manipulation,
    event_object_table,
    action_statement,
    action_timing,
    action_orientation
FROM information_schema.triggers
WHERE trigger_name = 'your_trigger_name';

1. Combine with function inspection to see the complete picture:

SELECT prosrc FROM pg_proc WHERE proname = 'log_product_changes';

2. For triggers on system tables, add schema qualification:

SELECT pg_get_triggerdef(t.oid)
FROM pg_trigger t
JOIN pg_class c ON t.tgrelid = c.oid
WHERE t.tgname = 'your_trigger'
AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'your_schema');