SlideShare a Scribd company logo
1 of 43
Download to read offline
Introduction to
Triggers
Who am I?
• Jim Mlodgenski
– jimm@openscg.com
– @jim_mlodgenski
• Director
– United States PostgreSQL (www.postgresql.us)
• Co-organizer of
– Philly PUG (www.phlpug.org)
– NYC PUG (www.nycpug.org)
• CTO, OpenSCG
– www.openscg.com
Triggers
• Code that gets executed when an
event happens in the database
– INSERT, UPDATE, DELETE
• Event Triggers fire on DDL
– CREATE, DROP, ALTER
– Still not mature yet
●
(limited functionaity)
Use Cases
• Table Partitioning
• Automatically generate derived column
values
• Enforce complex constraints
• Enforce referential integrity across nodes in a
distributed database
• Provide transparent event logging
• Provide auditing
• Invalidate cache entries
Structure
● Trigger
● Trigger Function
CREATE TRIGGER foo_trg
BEFORE UPDATE ON foo
FOR EACH ROW
EXECUTE PROCEDURE
foo_update();
Trigger Events
● Insert
● Update
● Delete
● Truncate
Trigger Timing
● Before
– The trigger is fired before the change is made
to the table
● After
– The trigger is fired after the change is made to
the table
Trigger Frequency
● For Each Row
– The trigger is fired once each time a row is
affected
● For Each Statement
– The trigger is fired once each time a statement
is executed
Trigger Overhead
CREATE UNLOGGED TABLE trigger_test (
key serial primary key,
value varchar,
insert_ts timestamp,
update_ts timestamp
);
INSERT INTO trigger_test (value) VALUES
(‘hello’);
set keys :scale
setrandom key 1 :keys
UPDATE trigger_test SET value = 'HELLO' WHERE
key = :key;
Trigger Overhead
pgbench -n -t 100000
-f INSERTS.pgbench postgres
pgbench -n -s 100000 -t 10000
-f UPDATES.pgbench postgres
Inserts: 4510 tps
Updates: 4349 tps
Trigger Overhead
CREATE FUNCTION empty_trigger()
RETURNS trigger AS $$
BEGIN
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER empty_trigger BEFORE
INSERT OR UPDATE ON trigger_test
FOR EACH ROW EXECUTE PROCEDURE
empty_trigger();
Trigger Overhead
pgbench -n -t 100000
-f INSERTS.pgbench postgres
pgbench -n -s 100000 -t 10000
-f UPDATES.pgbench postgres
Inserts: 4296 tps (4.8% overhead)
Updates: 3988 tps (8.3% overhead)
Trigger Arguments
● NEW
– Variable holding the new row for
INSERT/UPDATE operations in row-level triggers
● OLD
– Variable holding the old row for UPDATE/DELETE
operations in row-level triggers
NEW vs OLD
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
old_row json,
new_row json
);
NEW vs OLD (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP,
CURRENT_USER,
row_to_json(OLD),
row_to_json(NEW));
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
NEW vs OLD (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_OP
– A string of INSERT, UPDATE, DELETE, or TRUNCATE
telling for which operation the trigger was fired
● TG_NAME
– Variable that contains the name of the trigger actually
fired
● TG_WHEN
– A string of BEFORE, AFTER, or INSTEAD OF, depending
on the trigger's definition
● TG_LEVEL
– A string of either ROW or STATEMENT depending on the
trigger's definition
TG_OP
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
operation varchar NOT NULL,
old_row json,
new_row json
);
TG_OP (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
row_to_json(OLD), null);
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
row_to_json(OLD), row_to_json(NEW));
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
null, row_to_json(NEW));
RETURN NEW;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
TG_OP (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_TABLE_NAME
– The name of the table that caused the trigger
invocation.
● TG_RELNAME
– The name of the table that caused the trigger
invocation
● TG_RELID
– The object ID of the table that caused the trigger
invocation
● TG_TABLE_SCHEMA
– The name of the schema of the table that caused the
trigger invocation
TG_TABLE_NAME
CREATE TABLE audit (
event_time timestamp NOT NULL,
user_name varchar NOT NULL,
operation varchar NOT NULL,
table_name varchar NOT NULL,
old_row json,
new_row json
);
TG_TABLE_NAME (cont.)
CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, row_to_json(OLD), null);
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, row_to_json(OLD), row_to_json(NEW));
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO audit
VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP,
TG_TABLE_NAME, null, row_to_json(NEW));
RETURN NEW;
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
TG_TABLE_NAME (cont.)
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_branches
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
CREATE TRIGGER audit_trigger
AFTER UPDATE OR INSERT OR DELETE
ON pgbench_tellers
FOR EACH ROW
EXECUTE PROCEDURE audit_trigger();
Trigger Arguments (cont.)
● TG_NARGS
– The number of arguments given to the trigger
procedure in the CREATE TRIGGER statement
● TG_ARGV[]
– The arguments from the CREATE TRIGGER
statement
Trigger Use Cases
● Table Partitioning
– Splitting what is logically one large table into
smaller physical pieces
– Used to:
● Increase performance
● Archive data
● Storage tiering
Table Partitioning
CREATE TABLE audit_2014 (
CHECK ( event_time >= DATE '2014-01-01'
AND event_time < DATE '2015-01-01')
) INHERITS (audit);
CREATE TABLE audit_2015 (
CHECK ( event_time >= DATE '2015-01-01'
AND event_time < DATE '2016-01-01')
) INHERITS (audit);
Table Partitioning (cont.)
CREATE OR REPLACE FUNCTION partition_audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
EXECUTE 'INSERT INTO audit_' ||
to_char(NEW.event_time, 'YYYY') ||
' VALUES ($1, $2, $3, $4, $5, $6)'
USING NEW.event_time, NEW.user_name, NEW.operation,
NEW.table_name, NEW.old_row, NEW.new_row;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Table Partitioning (cont.)
CREATE TRIGGER partition_audit_trigger
BEFORE INSERT ON audit
FOR EACH ROW
EXECUTE PROCEDURE
partition_audit_trigger();
Partitioning Performance
CREATE OR REPLACE FUNCTION partition_audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF ( NEW.event_time >= DATE '2015-01-01' AND
NEW.event_time < DATE '2016-01-01' ) THEN
INSERT INTO audit_2015 VALUES (NEW.*);
ELSIF ( NEW.event_time >= DATE '2014-01-01' AND
NEW.event_time < DATE '2015-01-01' ) THEN
INSERT INTO audit_2014 VALUES (NEW.*);
ELSE
RAISE EXCEPTION 'Date out of range. Fix
partition_audit_trigger() function!';
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Moving Partitions
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2014
FOR EACH ROW EXECUTE PROCEDURE
move_partition_audit_trigger('2014-01-01', '2015-01-01');
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2015
FOR EACH ROW EXECUTE PROCEDURE
move_partition_audit_trigger('2015-01-01', '2016-01-01');
Moving Partitions (cont.)
CREATE OR REPLACE FUNCTION move_partition_audit_trigger()
RETURNS TRIGGER AS $$
DECLARE
start_date DATE;
end_date DATE;
BEGIN
start_date := TG_ARGV[0];
end_date := TG_ARGV[1];
IF ( NEW.event_time IS DISTINCT FROM OLD.event_time ) THEN
IF (NEW.event_time < start_date OR NEW.event_time >= end_date) THEN
EXECUTE 'DELETE FROM ' || TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME ||
' WHERE ctid = $1'
USING OLD.ctid;
INSERT INTO audit VALUES (NEW.*);
RETURN null;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Moving Partitions (cont.)
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2014
FOR EACH ROW
WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time)
EXECUTE PROCEDURE
move_partition_audit_trigger('2014-01-01', '2015-01-01');
CREATE TRIGGER move_partition_audit_trigger
BEFORE UPDATE
ON audit_2015
FOR EACH ROW
WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time)
EXECUTE PROCEDURE
move_partition_audit_trigger('2015-01-01', '2016-01-01');
Trigger Use Cases
● Calculate columns
– Calculate complex values
– Extract values from complex structures
– Used to:
● Increase performance
● Simplify queries
Extract JSON
$ head -n 5 zips.json
{ "_id" : "01001", "city" : "AGAWAM",
"loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" }
{ "_id" : "01002", "city" : "CUSHMAN",
"loc" : [ -72.51564999999999, 42.377017 ], "pop" : 36963, "state" : "MA" }
{ "_id" : "01005", "city" : "BARRE",
"loc" : [ -72.10835400000001, 42.409698 ], "pop" : 4546, "state" : "MA" }
{ "_id" : "01007", "city" : "BELCHERTOWN",
"loc" : [ -72.41095300000001, 42.275103 ], "pop" : 10579, "state" : "MA" }
{ "_id" : "01008", "city" : "BLANDFORD",
"loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" }
CREATE TABLE zips (
zip_code varchar PRIMARY KEY,
state varchar,
data json
);
Extract JSON
CREATE OR REPLACE FUNCTION extract_data_trigger()
RETURNS TRIGGER AS $$
BEGIN
NEW.zip_code := NEW.data->>'_id';
NEW.state := NEW.data->>'state';
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER extract_data_trigger
BEFORE UPDATE OR INSERT
ON zips
FOR EACH ROW EXECUTE PROCEDURE extract_data_trigger();
Trigger Use Cases
● Cache invalidation
– Remove stale entries from a cache
– The database tracks all data so is the single
source of truth
– Used to:
● Simplify cache management
● Remove application complexity
Note: Foreign Data Wrappers simplify this
process significantly
Cache Invalidation
CREATE TABLE users (
id serial PRIMARY KEY,
first_name varchar,
last_name varchar,
email_address varchar NOT NULL,
password_md5 varchar NOT NULL
);
CREATE OR REPLACE FUNCTION remove_cache_trigger()
RETURNS TRIGGER AS $$
BEGIN
DELETE from myredis_cache
WHERE key = OLD.id::varchar;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER remove_cache_trigger
AFTER UPDATE OR DELETE
ON users
FOR EACH ROW EXECUTE PROCEDURE remove_cache_trigger();
Cache Invalidation - Async
CREATE OR REPLACE FUNCTION remove_cache_trigger()
RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify(TG_TABLE_NAME, OLD.id::varchar);
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Things to Remember
● Triggers are part of the parent
transaction
– The trigger fails, the main transaction fails
– If the trigger takes a long time, the whole
transaction timing is affected
● Triggers can be difficult to debug
– Especially cascaded triggers
Trigger Function Language
Questions?

More Related Content

What's hot

Cassandra Materialized Views
Cassandra Materialized ViewsCassandra Materialized Views
Cassandra Materialized ViewsCarl Yeksigian
 
Implementing Highly Performant Distributed Aggregates
Implementing Highly Performant Distributed AggregatesImplementing Highly Performant Distributed Aggregates
Implementing Highly Performant Distributed AggregatesScyllaDB
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Traceoysteing
 
JavaScript - Chapter 15 - Debugging Techniques
 JavaScript - Chapter 15 - Debugging Techniques JavaScript - Chapter 15 - Debugging Techniques
JavaScript - Chapter 15 - Debugging TechniquesWebStackAcademy
 
High Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando PatroniHigh Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando PatroniZalando Technology
 
How the Postgres Query Optimizer Works
How the Postgres Query Optimizer WorksHow the Postgres Query Optimizer Works
How the Postgres Query Optimizer WorksEDB
 
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...rehaniltifat
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performanceoysteing
 
Introduction to PL/SQL
Introduction to PL/SQLIntroduction to PL/SQL
Introduction to PL/SQLKailash N
 
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)Hemant Kumar Singh
 
PostgreSQL Replication High Availability Methods
PostgreSQL Replication High Availability MethodsPostgreSQL Replication High Availability Methods
PostgreSQL Replication High Availability MethodsMydbops
 
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with TracingAnalyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with TracingScyllaDB
 
Introduction to GoLang
Introduction to GoLangIntroduction to GoLang
Introduction to GoLangNVISIA
 
PostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsPostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsCommand Prompt., Inc
 
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenKevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenPostgresOpen
 

What's hot (20)

Cassandra Materialized Views
Cassandra Materialized ViewsCassandra Materialized Views
Cassandra Materialized Views
 
Implementing Highly Performant Distributed Aggregates
Implementing Highly Performant Distributed AggregatesImplementing Highly Performant Distributed Aggregates
Implementing Highly Performant Distributed Aggregates
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Trace
 
trigger dbms
trigger dbmstrigger dbms
trigger dbms
 
JavaScript - Chapter 15 - Debugging Techniques
 JavaScript - Chapter 15 - Debugging Techniques JavaScript - Chapter 15 - Debugging Techniques
JavaScript - Chapter 15 - Debugging Techniques
 
High Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando PatroniHigh Availability PostgreSQL with Zalando Patroni
High Availability PostgreSQL with Zalando Patroni
 
How the Postgres Query Optimizer Works
How the Postgres Query Optimizer WorksHow the Postgres Query Optimizer Works
How the Postgres Query Optimizer Works
 
PL/SQL TRIGGERS
PL/SQL TRIGGERSPL/SQL TRIGGERS
PL/SQL TRIGGERS
 
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
 
Sql operator
Sql operatorSql operator
Sql operator
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performance
 
Introduction to PL/SQL
Introduction to PL/SQLIntroduction to PL/SQL
Introduction to PL/SQL
 
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
 
PostgreSQL Replication High Availability Methods
PostgreSQL Replication High Availability MethodsPostgreSQL Replication High Availability Methods
PostgreSQL Replication High Availability Methods
 
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with TracingAnalyze Virtual Machine Overhead Compared to Bare Metal with Tracing
Analyze Virtual Machine Overhead Compared to Bare Metal with Tracing
 
Introduction to GoLang
Introduction to GoLangIntroduction to GoLang
Introduction to GoLang
 
Introduction to sql
Introduction to sqlIntroduction to sql
Introduction to sql
 
PostgreSQL Administration for System Administrators
PostgreSQL Administration for System AdministratorsPostgreSQL Administration for System Administrators
PostgreSQL Administration for System Administrators
 
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres OpenKevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
Kevin Kempter PostgreSQL Backup and Recovery Methods @ Postgres Open
 
Views, Triggers, Functions, Stored Procedures, Indexing and Joins
Views, Triggers, Functions, Stored Procedures,  Indexing and JoinsViews, Triggers, Functions, Stored Procedures,  Indexing and Joins
Views, Triggers, Functions, Stored Procedures, Indexing and Joins
 

Similar to An Introduction To PostgreSQL Triggers

Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Thuan Nguyen
 
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenKeith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenPostgresOpen
 
Major features postgres 11
Major features postgres 11Major features postgres 11
Major features postgres 11EDB
 
Procedures and triggers in SQL
Procedures and triggers in SQLProcedures and triggers in SQL
Procedures and triggers in SQLVikash Sharma
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for OracleJacek Gebal
 
PostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesPostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesSaiful
 
Oracle trigger
Oracle triggerOracle trigger
Oracle triggernasrul28
 
Function Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfFunction Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfSanam Maharjan
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq lsInSync Conference
 
Database Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersDatabase Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersAbdul Rahman Sherzad
 
Changing your huge table's data types in production
Changing your huge table's data types in productionChanging your huge table's data types in production
Changing your huge table's data types in productionJimmy Angelakos
 
Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Leon Rzhemovskiy
 
Below is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfBelow is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfaroraenterprisesmbd
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .NetKathiK58
 
Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009mattsmiley
 

Similar to An Introduction To PostgreSQL Triggers (20)

Unit 4
Unit 4Unit 4
Unit 4
 
Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17Oracle - Program with PL/SQL - Lession 17
Oracle - Program with PL/SQL - Lession 17
 
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres OpenKeith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
Keith Fiske - When PostgreSQL Can't, You Can @ Postgres Open
 
Major features postgres 11
Major features postgres 11Major features postgres 11
Major features postgres 11
 
Procedures and triggers in SQL
Procedures and triggers in SQLProcedures and triggers in SQL
Procedures and triggers in SQL
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
 
PostgreSQL 9.5 Features
PostgreSQL 9.5 FeaturesPostgreSQL 9.5 Features
PostgreSQL 9.5 Features
 
Oracle trigger
Oracle triggerOracle trigger
Oracle trigger
 
Function Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdfFunction Procedure Trigger Partition.pdf
Function Procedure Trigger Partition.pdf
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
 
Database Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event SchedulersDatabase Automation with MySQL Triggers and Event Schedulers
Database Automation with MySQL Triggers and Event Schedulers
 
Changing your huge table's data types in production
Changing your huge table's data types in productionChanging your huge table's data types in production
Changing your huge table's data types in production
 
Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14Oracle_Audit_APEX IOUG Collaborate 14
Oracle_Audit_APEX IOUG Collaborate 14
 
Triggers
TriggersTriggers
Triggers
 
Below is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdfBelow is the question I need help with. It need to be done in Java. .pdf
Below is the question I need help with. It need to be done in Java. .pdf
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .Net
 
Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009Basic Query Tuning Primer - Pg West 2009
Basic Query Tuning Primer - Pg West 2009
 
Basic Query Tuning Primer
Basic Query Tuning PrimerBasic Query Tuning Primer
Basic Query Tuning Primer
 
Good Tests Bad Tests
Good Tests Bad TestsGood Tests Bad Tests
Good Tests Bad Tests
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 

More from Jim Mlodgenski

Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLJim Mlodgenski
 
Oracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesOracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesJim Mlodgenski
 
Debugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeDebugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeJim Mlodgenski
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasJim Mlodgenski
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQLJim Mlodgenski
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentJim Mlodgenski
 
Scaling PostreSQL with Stado
Scaling PostreSQL with StadoScaling PostreSQL with Stado
Scaling PostreSQL with StadoJim Mlodgenski
 
Multi-Master Replication with Slony
Multi-Master Replication with SlonyMulti-Master Replication with Slony
Multi-Master Replication with SlonyJim Mlodgenski
 
Scaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLScaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLJim Mlodgenski
 

More from Jim Mlodgenski (12)

Strategic autovacuum
Strategic autovacuumStrategic autovacuum
Strategic autovacuum
 
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
 
Oracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakesOracle postgre sql-mirgration-top-10-mistakes
Oracle postgre sql-mirgration-top-10-mistakes
 
Profiling PL/pgSQL
Profiling PL/pgSQLProfiling PL/pgSQL
Profiling PL/pgSQL
 
Debugging Your PL/pgSQL Code
Debugging Your PL/pgSQL CodeDebugging Your PL/pgSQL Code
Debugging Your PL/pgSQL Code
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
 
Introduction to PostgreSQL
Introduction to PostgreSQLIntroduction to PostgreSQL
Introduction to PostgreSQL
 
Postgresql Federation
Postgresql FederationPostgresql Federation
Postgresql Federation
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL Environment
 
Scaling PostreSQL with Stado
Scaling PostreSQL with StadoScaling PostreSQL with Stado
Scaling PostreSQL with Stado
 
Multi-Master Replication with Slony
Multi-Master Replication with SlonyMulti-Master Replication with Slony
Multi-Master Replication with Slony
 
Scaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQLScaling PostgreSQL With GridSQL
Scaling PostgreSQL With GridSQL
 

Recently uploaded

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 

Recently uploaded (20)

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 

An Introduction To PostgreSQL Triggers

  • 2. Who am I? • Jim Mlodgenski – jimm@openscg.com – @jim_mlodgenski • Director – United States PostgreSQL (www.postgresql.us) • Co-organizer of – Philly PUG (www.phlpug.org) – NYC PUG (www.nycpug.org) • CTO, OpenSCG – www.openscg.com
  • 3.
  • 4. Triggers • Code that gets executed when an event happens in the database – INSERT, UPDATE, DELETE • Event Triggers fire on DDL – CREATE, DROP, ALTER – Still not mature yet ● (limited functionaity)
  • 5. Use Cases • Table Partitioning • Automatically generate derived column values • Enforce complex constraints • Enforce referential integrity across nodes in a distributed database • Provide transparent event logging • Provide auditing • Invalidate cache entries
  • 6. Structure ● Trigger ● Trigger Function CREATE TRIGGER foo_trg BEFORE UPDATE ON foo FOR EACH ROW EXECUTE PROCEDURE foo_update();
  • 7. Trigger Events ● Insert ● Update ● Delete ● Truncate
  • 8. Trigger Timing ● Before – The trigger is fired before the change is made to the table ● After – The trigger is fired after the change is made to the table
  • 9. Trigger Frequency ● For Each Row – The trigger is fired once each time a row is affected ● For Each Statement – The trigger is fired once each time a statement is executed
  • 10. Trigger Overhead CREATE UNLOGGED TABLE trigger_test ( key serial primary key, value varchar, insert_ts timestamp, update_ts timestamp ); INSERT INTO trigger_test (value) VALUES (‘hello’); set keys :scale setrandom key 1 :keys UPDATE trigger_test SET value = 'HELLO' WHERE key = :key;
  • 11. Trigger Overhead pgbench -n -t 100000 -f INSERTS.pgbench postgres pgbench -n -s 100000 -t 10000 -f UPDATES.pgbench postgres Inserts: 4510 tps Updates: 4349 tps
  • 12. Trigger Overhead CREATE FUNCTION empty_trigger() RETURNS trigger AS $$ BEGIN RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER empty_trigger BEFORE INSERT OR UPDATE ON trigger_test FOR EACH ROW EXECUTE PROCEDURE empty_trigger();
  • 13. Trigger Overhead pgbench -n -t 100000 -f INSERTS.pgbench postgres pgbench -n -s 100000 -t 10000 -f UPDATES.pgbench postgres Inserts: 4296 tps (4.8% overhead) Updates: 3988 tps (8.3% overhead)
  • 14. Trigger Arguments ● NEW – Variable holding the new row for INSERT/UPDATE operations in row-level triggers ● OLD – Variable holding the old row for UPDATE/DELETE operations in row-level triggers
  • 15. NEW vs OLD CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, old_row json, new_row json );
  • 16. NEW vs OLD (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 17. NEW vs OLD (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 18. Trigger Arguments (cont.) ● TG_OP – A string of INSERT, UPDATE, DELETE, or TRUNCATE telling for which operation the trigger was fired ● TG_NAME – Variable that contains the name of the trigger actually fired ● TG_WHEN – A string of BEFORE, AFTER, or INSTEAD OF, depending on the trigger's definition ● TG_LEVEL – A string of either ROW or STATEMENT depending on the trigger's definition
  • 19. TG_OP CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, operation varchar NOT NULL, old_row json, new_row json );
  • 20. TG_OP (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, row_to_json(OLD), null); RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, null, row_to_json(NEW)); RETURN NEW; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 21. TG_OP (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 22. Trigger Arguments (cont.) ● TG_TABLE_NAME – The name of the table that caused the trigger invocation. ● TG_RELNAME – The name of the table that caused the trigger invocation ● TG_RELID – The object ID of the table that caused the trigger invocation ● TG_TABLE_SCHEMA – The name of the schema of the table that caused the trigger invocation
  • 23. TG_TABLE_NAME CREATE TABLE audit ( event_time timestamp NOT NULL, user_name varchar NOT NULL, operation varchar NOT NULL, table_name varchar NOT NULL, old_row json, new_row json );
  • 24. TG_TABLE_NAME (cont.) CREATE OR REPLACE FUNCTION audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF (TG_OP = 'DELETE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, row_to_json(OLD), null); RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, row_to_json(OLD), row_to_json(NEW)); RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO audit VALUES (CURRENT_TIMESTAMP, CURRENT_USER,TG_OP, TG_TABLE_NAME, null, row_to_json(NEW)); RETURN NEW; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 25. TG_TABLE_NAME (cont.) CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_branches FOR EACH ROW EXECUTE PROCEDURE audit_trigger(); CREATE TRIGGER audit_trigger AFTER UPDATE OR INSERT OR DELETE ON pgbench_tellers FOR EACH ROW EXECUTE PROCEDURE audit_trigger();
  • 26. Trigger Arguments (cont.) ● TG_NARGS – The number of arguments given to the trigger procedure in the CREATE TRIGGER statement ● TG_ARGV[] – The arguments from the CREATE TRIGGER statement
  • 27. Trigger Use Cases ● Table Partitioning – Splitting what is logically one large table into smaller physical pieces – Used to: ● Increase performance ● Archive data ● Storage tiering
  • 28. Table Partitioning CREATE TABLE audit_2014 ( CHECK ( event_time >= DATE '2014-01-01' AND event_time < DATE '2015-01-01') ) INHERITS (audit); CREATE TABLE audit_2015 ( CHECK ( event_time >= DATE '2015-01-01' AND event_time < DATE '2016-01-01') ) INHERITS (audit);
  • 29. Table Partitioning (cont.) CREATE OR REPLACE FUNCTION partition_audit_trigger() RETURNS TRIGGER AS $$ BEGIN EXECUTE 'INSERT INTO audit_' || to_char(NEW.event_time, 'YYYY') || ' VALUES ($1, $2, $3, $4, $5, $6)' USING NEW.event_time, NEW.user_name, NEW.operation, NEW.table_name, NEW.old_row, NEW.new_row; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 30. Table Partitioning (cont.) CREATE TRIGGER partition_audit_trigger BEFORE INSERT ON audit FOR EACH ROW EXECUTE PROCEDURE partition_audit_trigger();
  • 31. Partitioning Performance CREATE OR REPLACE FUNCTION partition_audit_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.event_time >= DATE '2015-01-01' AND NEW.event_time < DATE '2016-01-01' ) THEN INSERT INTO audit_2015 VALUES (NEW.*); ELSIF ( NEW.event_time >= DATE '2014-01-01' AND NEW.event_time < DATE '2015-01-01' ) THEN INSERT INTO audit_2014 VALUES (NEW.*); ELSE RAISE EXCEPTION 'Date out of range. Fix partition_audit_trigger() function!'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  • 32. Moving Partitions CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2014 FOR EACH ROW EXECUTE PROCEDURE move_partition_audit_trigger('2014-01-01', '2015-01-01'); CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2015 FOR EACH ROW EXECUTE PROCEDURE move_partition_audit_trigger('2015-01-01', '2016-01-01');
  • 33. Moving Partitions (cont.) CREATE OR REPLACE FUNCTION move_partition_audit_trigger() RETURNS TRIGGER AS $$ DECLARE start_date DATE; end_date DATE; BEGIN start_date := TG_ARGV[0]; end_date := TG_ARGV[1]; IF ( NEW.event_time IS DISTINCT FROM OLD.event_time ) THEN IF (NEW.event_time < start_date OR NEW.event_time >= end_date) THEN EXECUTE 'DELETE FROM ' || TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME || ' WHERE ctid = $1' USING OLD.ctid; INSERT INTO audit VALUES (NEW.*); RETURN null; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 34. Moving Partitions (cont.) CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2014 FOR EACH ROW WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time) EXECUTE PROCEDURE move_partition_audit_trigger('2014-01-01', '2015-01-01'); CREATE TRIGGER move_partition_audit_trigger BEFORE UPDATE ON audit_2015 FOR EACH ROW WHEN (NEW.event_time IS DISTINCT FROM OLD.event_time) EXECUTE PROCEDURE move_partition_audit_trigger('2015-01-01', '2016-01-01');
  • 35. Trigger Use Cases ● Calculate columns – Calculate complex values – Extract values from complex structures – Used to: ● Increase performance ● Simplify queries
  • 36. Extract JSON $ head -n 5 zips.json { "_id" : "01001", "city" : "AGAWAM", "loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" } { "_id" : "01002", "city" : "CUSHMAN", "loc" : [ -72.51564999999999, 42.377017 ], "pop" : 36963, "state" : "MA" } { "_id" : "01005", "city" : "BARRE", "loc" : [ -72.10835400000001, 42.409698 ], "pop" : 4546, "state" : "MA" } { "_id" : "01007", "city" : "BELCHERTOWN", "loc" : [ -72.41095300000001, 42.275103 ], "pop" : 10579, "state" : "MA" } { "_id" : "01008", "city" : "BLANDFORD", "loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" } CREATE TABLE zips ( zip_code varchar PRIMARY KEY, state varchar, data json );
  • 37. Extract JSON CREATE OR REPLACE FUNCTION extract_data_trigger() RETURNS TRIGGER AS $$ BEGIN NEW.zip_code := NEW.data->>'_id'; NEW.state := NEW.data->>'state'; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER extract_data_trigger BEFORE UPDATE OR INSERT ON zips FOR EACH ROW EXECUTE PROCEDURE extract_data_trigger();
  • 38. Trigger Use Cases ● Cache invalidation – Remove stale entries from a cache – The database tracks all data so is the single source of truth – Used to: ● Simplify cache management ● Remove application complexity Note: Foreign Data Wrappers simplify this process significantly
  • 39. Cache Invalidation CREATE TABLE users ( id serial PRIMARY KEY, first_name varchar, last_name varchar, email_address varchar NOT NULL, password_md5 varchar NOT NULL ); CREATE OR REPLACE FUNCTION remove_cache_trigger() RETURNS TRIGGER AS $$ BEGIN DELETE from myredis_cache WHERE key = OLD.id::varchar; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER remove_cache_trigger AFTER UPDATE OR DELETE ON users FOR EACH ROW EXECUTE PROCEDURE remove_cache_trigger();
  • 40. Cache Invalidation - Async CREATE OR REPLACE FUNCTION remove_cache_trigger() RETURNS TRIGGER AS $$ BEGIN PERFORM pg_notify(TG_TABLE_NAME, OLD.id::varchar); RETURN NEW; END; $$ LANGUAGE plpgsql;
  • 41. Things to Remember ● Triggers are part of the parent transaction – The trigger fails, the main transaction fails – If the trigger takes a long time, the whole transaction timing is affected ● Triggers can be difficult to debug – Especially cascaded triggers