Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Row-level vs Statement-level Triggers in PostgreSQL
📖 Scenario: You are managing a PostgreSQL database for a small online store. You want to track changes to the orders table. Specifically, you want to log each individual order change and also keep a count of how many changes happen in a batch.
🎯 Goal: Build two triggers on the orders table: one row-level trigger that logs each changed order, and one statement-level trigger that counts how many changes happened in a statement.
📋 What You'll Learn
Create an orders table with columns order_id (integer primary key) and amount (numeric).
Create a log_changes table to store logs of individual order changes with columns order_id and changed_at timestamp.
Create a change_count table to store the count of changes per statement with columns count_id (serial primary key) and change_total integer.
Write a row-level trigger function that inserts a row into log_changes for each changed order.
Write a statement-level trigger function that inserts a row into change_count with the total number of changes in the statement.
Attach the row-level trigger to fire AFTER each row update on orders.
Attach the statement-level trigger to fire AFTER the entire UPDATE statement on orders.
💡 Why This Matters
🌍 Real World
Triggers help automate tasks like auditing changes or enforcing rules in databases used by businesses.
💼 Career
Understanding triggers is important for database administrators and backend developers to maintain data integrity and automate workflows.
Progress0 / 4 steps
1
Create the orders and log_changes tables
Create a table called orders with columns order_id as integer primary key and amount as numeric. Also create a table called log_changes with columns order_id as integer and changed_at as timestamp without time zone.
PostgreSQL
Hint
Use CREATE TABLE statements with the exact column names and types.
2
Create the change_count table
Create a table called change_count with columns count_id as serial primary key and change_total as integer.
PostgreSQL
Hint
Use SERIAL for auto-incrementing primary key.
3
Write the row-level trigger function
Write a function called log_order_change that returns trigger. This function should insert into log_changes the order_id from NEW and the current timestamp using NOW(). The function should return NEW.
PostgreSQL
Hint
Use NEW.order_id to get the updated row's order_id and NOW() for the timestamp.
4
Create triggers for row-level and statement-level events
Create a row-level trigger called after_order_update_row that fires AFTER UPDATE on orders for EACH ROW and calls log_order_change. Then create a statement-level trigger called after_order_update_stmt that fires AFTER UPDATE on orders for EACH STATEMENT and calls a new function count_order_changes. Also write the count_order_changes function that inserts the number of rows affected by the statement into change_count using GET DIAGNOSTICS to get the row count.
PostgreSQL
Hint
Use GET DIAGNOSTICS to get the number of rows affected by the statement. Attach triggers with CREATE TRIGGER specifying FOR EACH ROW or FOR EACH STATEMENT.
Practice
(1/5)
1. What is the main difference between a row-level trigger and a statement-level trigger in PostgreSQL?
easy
A. Row-level triggers only work on INSERT; statement-level triggers only work on UPDATE.
B. Row-level triggers execute once per SQL statement; statement-level triggers execute once for each affected row.
C. Row-level triggers execute once for each affected row; statement-level triggers execute once per SQL statement.
D. Row-level triggers cannot modify data; statement-level triggers can modify data.
Solution
Step 1: Understand trigger execution scope
Row-level triggers run once for every row affected by the SQL command, meaning if 10 rows are updated, the trigger runs 10 times.
Statement-level triggers run only once per SQL command, regardless of how many rows are affected.
Final Answer:
Row-level triggers execute once for each affected row; statement-level triggers execute once per SQL statement. -> Option C
Quick Check:
Row-level = per row, Statement-level = per statement [OK]
Hint: Row-level = per row; statement-level = per statement [OK]
Common Mistakes:
Confusing which trigger runs per row vs per statement
Thinking row-level triggers run only once per statement
Assuming statement-level triggers run per row
Believing trigger types depend on operation type (INSERT/UPDATE)
2. Which of the following is the correct syntax to create a row-level trigger in PostgreSQL?
easy
A. CREATE TRIGGER trg AFTER INSERT ON table FOR EACH ROW EXECUTE FUNCTION func();
B. CREATE TRIGGER trg AFTER INSERT ON table FOR EACH STATEMENT EXECUTE FUNCTION func();
C. CREATE TRIGGER trg AFTER INSERT ON table EXECUTE FUNCTION func();
D. CREATE TRIGGER trg FOR EACH ROW EXECUTE FUNCTION func();
Solution
Step 1: Identify correct trigger syntax
The syntax for creating a row-level trigger requires the clause FOR EACH ROW to specify it runs per affected row.
Step 2: Check full syntax correctness
CREATE TRIGGER trg AFTER INSERT ON table FOR EACH ROW EXECUTE FUNCTION func(); correctly includes AFTER INSERT, ON table, FOR EACH ROW, and EXECUTE FUNCTION func(); which is the proper syntax.
Final Answer:
CREATE TRIGGER trg AFTER INSERT ON table FOR EACH ROW EXECUTE FUNCTION func(); -> Option A
Quick Check:
Row-level triggers use FOR EACH ROW [OK]
Hint: Row-level triggers always use FOR EACH ROW clause [OK]
Common Mistakes:
Omitting FOR EACH ROW for row-level triggers
Using FOR EACH STATEMENT for row-level triggers
Missing EXECUTE FUNCTION keyword
Incorrect order of clauses
3. Consider this trigger function and trigger:
CREATE FUNCTION trg_func() RETURNS trigger AS $$ BEGIN RAISE NOTICE 'Triggered'; RETURN NEW; END; $$ LANGUAGE plpgsql;
CREATE TRIGGER trg AFTER UPDATE ON employees FOR EACH ROW EXECUTE FUNCTION trg_func();
UPDATE employees SET salary = salary * 1.1 WHERE department = 'Sales';
What will be the output when the UPDATE affects 3 rows?
medium
A. The notice 'Triggered' will appear 3 times.
B. The notice 'Triggered' will appear once.
C. No notice will appear because AFTER UPDATE triggers do not raise notices.
D. The notice 'Triggered' will appear once per statement plus once per row.
Solution
Step 1: Identify trigger type and execution count
The trigger is defined FOR EACH ROW, so it runs once for every row updated.
Step 2: Calculate total trigger executions
Since 3 rows are updated, the trigger function runs 3 times, each raising the notice 'Triggered'.
Final Answer:
The notice 'Triggered' will appear 3 times. -> Option A
Quick Check:
Row-level trigger runs per row = 3 notices [OK]
Hint: FOR EACH ROW triggers run once per affected row [OK]
Common Mistakes:
Assuming notice appears only once per statement
Confusing FOR EACH ROW with FOR EACH STATEMENT
Thinking AFTER UPDATE triggers don't raise notices
Believing trigger runs multiple times per row
4. You created a statement-level trigger but it seems to run multiple times when you update multiple rows. What is the most likely cause?
medium
A. PostgreSQL does not support statement-level triggers.
B. Statement-level triggers always run once per row by design.
C. The trigger function contains a loop causing multiple executions.
D. You accidentally defined the trigger as FOR EACH ROW instead of FOR EACH STATEMENT.
Solution
Step 1: Understand trigger definition impact
If a trigger runs multiple times per row update, it is likely defined as FOR EACH ROW, not FOR EACH STATEMENT.
Step 2: Verify PostgreSQL trigger capabilities
PostgreSQL supports both row-level and statement-level triggers; statement-level triggers run once per statement.
Final Answer:
You accidentally defined the trigger as FOR EACH ROW instead of FOR EACH STATEMENT. -> Option D
Quick Check:
FOR EACH ROW triggers run per row, causing multiple executions [OK]
Hint: Check FOR EACH ROW vs FOR EACH STATEMENT clause [OK]
Blaming trigger function code without checking trigger type
5. You want to log a summary message once after any UPDATE statement on a table, regardless of how many rows are changed. Which trigger type and timing should you use?
hard
A. A BEFORE UPDATE row-level trigger
B. An AFTER UPDATE statement-level trigger
C. An AFTER UPDATE row-level trigger
D. A BEFORE UPDATE statement-level trigger
Solution
Step 1: Determine trigger timing for logging after update
Logging after the update completes requires an AFTER trigger.
Step 2: Choose trigger level for single summary message
To log once per statement regardless of rows, use a statement-level trigger (FOR EACH STATEMENT).
Final Answer:
An AFTER UPDATE statement-level trigger -> Option B
Quick Check:
Summary logging = AFTER + statement-level trigger [OK]
Hint: Use AFTER statement-level trigger for single summary action [OK]
Common Mistakes:
Using row-level triggers causing multiple logs
Using BEFORE triggers missing final state
Confusing timing and level for logging
Assuming row-level triggers can log once per statement