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');