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