PostgreSQL教程FG153-PG触发器进阶:行级/语句级触发器与触发时机
本文档风哥主要介绍PostgreSQL数据库触发器的进阶知识,包括行级触发器、语句级触发器的区别与应用,以及不同触发时机的选择,风哥教程参考PostgreSQL官方文档Triggers、Event Triggers等内容,适合数据库开发人员和DBA在生产环境中使用触发器实现复杂业务逻辑。
Part01-基础概念与理论知识
1.1 PostgreSQL数据库触发器类型
PostgreSQL支持多种类型的触发器,主要包括行级触发器和语句级触发器。行级触发器在每行数据修改时触发,而语句级触发器在整个SQL语句执行前后触发。更多视频教程www.fgedu.net.cn。
- 行级触发器(FOR EACH ROW):对每一行数据的修改都会触发,适合需要处理每行数据的场景
- 语句级触发器(FOR EACH STATEMENT):整个SQL语句只触发一次,适合统计、日志等场景
- 约束触发器(CONSTRAINT TRIGGER):用于实现复杂的约束条件
- 事件触发器(EVENT TRIGGER):响应数据库对象变更事件
1.2 PostgreSQL数据库触发时机
触发时机决定了触发器在SQL语句执行的哪个阶段被调用:
- BEFORE:在SQL语句执行前触发,可用于数据验证和预处理
- AFTER:在SQL语句执行后触发,可用于审计和数据同步
- INSTEAD OF:替代SQL语句执行,可用于视图更新等场景
1.3 PostgreSQL数据库触发器执行机制
触发器的执行遵循一定的顺序:BEFORE语句级 → BEFORE行级 → 实际操作 → AFTER行级 → AFTER语句级。学习交流加群风哥微信: itpux-com。了解执行顺序对于设计复杂的触发器逻辑非常重要。
Part02-生产环境规划与建议
2.1 PostgreSQL数据库触发器设计原则
触发器设计原则:单一职责,每个触发器只做一件事;性能优先,避免在触发器中执行复杂操作;错误处理,提供清晰的错误信息;可维护性,编写清晰的代码和文档。
2.2 PostgreSQL数据库触发器性能优化
性能优化建议:避免在触发器中执行大量操作;使用批量处理;合理选择触发时机;定期维护触发器相关表的统计信息;监控触发器执行时间。
2.3 PostgreSQL数据库触发器安全考虑
安全考虑:避免在触发器中执行危险操作;使用SECURITY DEFINER时要谨慎;确保触发器函数有适当的权限;避免信息泄露。
Part03-生产环境项目实施方案
3.1 PostgreSQL数据库行级触发器实现
3.1.1 行级触发器创建
— 创建测试表
CREATE TABLE fgedu_employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
salary NUMERIC(10,2) NOT NULL,
department VARCHAR(100),
hire_date DATE DEFAULT NOW(),
last_update TIMESTAMP DEFAULT NOW()
);
— 输出结果
CREATE TABLE
— 插入测试数据
INSERT INTO fgedu_employees(name, salary, department)
VALUES
(‘张三’, 8000.00, ‘技术部’),
(‘李四’, 10000.00, ‘市场部’),
(‘王五’, 12000.00, ‘财务部’);
— 输出结果
INSERT 0 3
— 创建行级触发器函数
CREATE OR REPLACE FUNCTION fgedu_employee_audit()
RETURNS TRIGGER
AS $$
BEGIN
— 记录更新时间
NEW.last_update := NOW();
— 检查薪资范围
IF NEW.salary < 3000 THEN
RAISE EXCEPTION 'Salary cannot be less than 3000';
END IF;
-- 检查部门名称
IF NEW.department IS NULL THEN
NEW.department := '未分配';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 输出结果
CREATE FUNCTION
-- 创建BEFORE行级触发器
CREATE TRIGGER trg_employee_before
BEFORE INSERT OR UPDATE ON fgedu_employees
FOR EACH ROW
EXECUTE FUNCTION fgedu_employee_audit();
-- 输出结果
CREATE TRIGGER
-- 测试行级触发器
UPDATE fgedu_employees SET salary = 9000.00 WHERE id = 1;
-- 输出结果
UPDATE 1
-- 查看更新结果
SELECT * FROM fgedu_employees WHERE id = 1;
-- 输出结果
id | name | salary | department | hire_date | last_update
----+------+--------+------------+------------+------------------------
1 | 张三 | 9000.00| 技术部 | 2026-04-07 | 2026-04-07 16:00:00
(1 row)
-- 测试薪资检查
UPDATE fgedu_employees SET salary = 2000.00 WHERE id = 2;
-- 输出结果
ERROR: Salary cannot be less than 3000
-- 测试部门默认值
INSERT INTO fgedu_employees(name, salary)
VALUES('赵六', 7000.00);
-- 输出结果
INSERT 0 1
-- 查看插入结果
SELECT * FROM fgedu_employees WHERE name = '赵六';
-- 输出结果
id | name | salary | department | hire_date | last_update
----+------+--------+------------+------------+------------------------
4 | 赵六 | 7000.00| 未分配 | 2026-04-07 | 2026-04-07 16:00:00
(1 row)
3.2 PostgreSQL数据库语句级触发器实现
3.2.1 语句级触发器创建
— 创建操作日志表
CREATE TABLE fgedu_operation_log (
id BIGSERIAL PRIMARY KEY,
operation_type VARCHAR(50) NOT NULL,
table_name VARCHAR(100) NOT NULL,
affected_rows INTEGER,
operation_time TIMESTAMP DEFAULT NOW(),
operator VARCHAR(100) DEFAULT CURRENT_USER,
details TEXT
);
— 输出结果
CREATE TABLE
— 创建语句级触发器函数
CREATE OR REPLACE FUNCTION fgedu_operation_audit()
RETURNS TRIGGER
AS $$
DECLARE
v_row_count INTEGER;
BEGIN
GET DIAGNOSTICS v_row_count = ROW_COUNT;
INSERT INTO fgedu_operation_log(
operation_type,
table_name,
affected_rows,
details
)
VALUES(
TG_OP,
TG_TABLE_NAME,
v_row_count,
‘Statement executed: ‘ || TG_OP || ‘ on ‘ || TG_TABLE_NAME
);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
— 输出结果
CREATE FUNCTION
— 创建AFTER语句级触发器
CREATE TRIGGER trg_employee_statement
AFTER INSERT OR UPDATE OR DELETE ON fgedu_employees
FOR EACH STATEMENT
EXECUTE FUNCTION fgedu_operation_audit();
— 输出结果
CREATE TRIGGER
— 测试语句级触发器
UPDATE fgedu_employees SET salary = salary * 1.1 WHERE department = ‘技术部’;
— 输出结果
UPDATE 2
— 查看操作日志
SELECT * FROM fgedu_operation_log ORDER BY operation_time DESC LIMIT 5;
— 输出结果
id | operation_type | table_name | affected_rows | operation_time | operator | details
—-+—————-+————-+—————+————————+———-+—————————————-
1 | UPDATE | fgedu_employees | 2 | 2026-04-07 16:00:00 | fgedu | Statement executed: UPDATE on fgedu_employees
(1 row)
— 批量插入测试
INSERT INTO fgedu_employees(name, salary, department)
VALUES
(‘孙七’, 8500.00, ‘技术部’),
(‘周八’, 9500.00, ‘市场部’),
(‘吴九’, 11000.00, ‘财务部’);
— 输出结果
INSERT 0 3
— 查看操作日志
SELECT * FROM fgedu_operation_log ORDER BY operation_time DESC LIMIT 5;
— 输出结果
id | operation_type | table_name | affected_rows | operation_time | operator | details
—-+—————-+————-+—————+————————+———-+—————————————-
2 | INSERT | fgedu_employees | 3 | 2026-04-07 16:05:00 | fgedu | Statement executed: INSERT on fgedu_employees
1 | UPDATE | fgedu_employees | 2 | 2026-04-07 16:00:00 | fgedu | Statement executed: UPDATE on fgedu_employees
(2 rows)
3.3 PostgreSQL数据库复合触发器实现
3.3.1 复合触发器创建
— 创建复合触发器函数
CREATE OR REPLACE FUNCTION fgedu_compound_audit()
RETURNS TRIGGER
AS $$
BEGIN
IF TG_OP = ‘INSERT’ THEN
— 处理插入操作
IF TG_LEVEL = ‘ROW’ THEN
— 行级处理
NEW.last_update := NOW();
RETURN NEW;
ELSIF TG_LEVEL = ‘STATEMENT’ THEN
— 语句级处理
INSERT INTO fgedu_operation_log(
operation_type,
table_name,
details
)
VALUES(
‘INSERT’,
TG_TABLE_NAME,
‘Batch insert operation’
);
RETURN NULL;
END IF;
ELSIF TG_OP = ‘UPDATE’ THEN
— 处理更新操作
IF TG_LEVEL = ‘ROW’ THEN
— 行级处理
NEW.last_update := NOW();
RETURN NEW;
ELSIF TG_LEVEL = ‘STATEMENT’ THEN
— 语句级处理
INSERT INTO fgedu_operation_log(
operation_type,
table_name,
details
)
VALUES(
‘UPDATE’,
TG_TABLE_NAME,
‘Batch update operation’
);
RETURN NULL;
END IF;
ELSIF TG_OP = ‘DELETE’ THEN
— 处理删除操作
IF TG_LEVEL = ‘STATEMENT’ THEN
— 语句级处理
INSERT INTO fgedu_operation_log(
operation_type,
table_name,
details
)
VALUES(
‘DELETE’,
TG_TABLE_NAME,
‘Batch delete operation’
);
RETURN NULL;
END IF;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
— 输出结果
CREATE FUNCTION
— 先删除之前的触发器
DROP TRIGGER IF EXISTS trg_employee_before ON fgedu_employees;
DROP TRIGGER IF EXISTS trg_employee_statement ON fgedu_employees;
— 输出结果
DROP TRIGGER
DROP TRIGGER
— 创建BEFORE行级触发器
CREATE TRIGGER trg_employee_before_row
BEFORE INSERT OR UPDATE ON fgedu_employees
FOR EACH ROW
EXECUTE FUNCTION fgedu_compound_audit();
— 输出结果
CREATE TRIGGER
— 创建AFTER语句级触发器
CREATE TRIGGER trg_employee_after_statement
AFTER INSERT OR UPDATE OR DELETE ON fgedu_employees
FOR EACH STATEMENT
EXECUTE FUNCTION fgedu_compound_audit();
— 输出结果
CREATE TRIGGER
— 测试复合触发器
UPDATE fgedu_employees SET salary = salary + 500 WHERE department = ‘市场部’;
— 输出结果
UPDATE 2
— 查看操作日志
SELECT * FROM fgedu_operation_log ORDER BY operation_time DESC LIMIT 5;
— 输出结果
id | operation_type | table_name | affected_rows | operation_time | operator | details
—-+—————-+————-+—————+————————+———-+—————————————-
3 | UPDATE | fgedu_employees | NULL | 2026-04-07 16:10:00 | fgedu | Batch update operation
2 | INSERT | fgedu_employees | 3 | 2026-04-07 16:05:00 | fgedu | Statement executed: INSERT on fgedu_employees
1 | UPDATE | fgedu_employees | 2 | 2026-04-07 16:00:00 | fgedu | Statement executed: UPDATE on fgedu_employees
(3 rows)
— 查看更新结果
SELECT name, salary, last_update FROM fgedu_employees WHERE department = ‘市场部’;
— 输出结果
name | salary | last_update
——+——–+————————
李四 | 11500.00| 2026-04-07 16:10:00
周八 | 10000.00| 2026-04-07 16:10:00
(2 rows)
Part04-生产案例与实战讲解
4.1 PostgreSQL数据库审计触发器实战
本案例演示审计触发器的实现。学习交流加群风哥QQ113257174。
— 创建审计日志表
CREATE TABLE fgedu_audit_log (
id BIGSERIAL PRIMARY KEY,
table_name VARCHAR(100) NOT NULL,
operation_type VARCHAR(20) NOT NULL,
row_id INTEGER,
old_data JSONB,
new_data JSONB,
operation_time TIMESTAMP DEFAULT NOW(),
operator VARCHAR(100) DEFAULT CURRENT_USER,
client_ip INET DEFAULT inet_client_addr(),
fgapplication_name VARCHAR(100) DEFAULT current_setting(‘fgapplication_name’)
);
— 输出结果
CREATE TABLE
— 创建索引
CREATE INDEX idx_audit_log_table ON fgedu_audit_log(table_name);
CREATE INDEX idx_audit_log_time ON fgedu_audit_log(operation_time);
CREATE INDEX idx_audit_log_row ON fgedu_audit_log(table_name, row_id);
— 输出结果
CREATE INDEX
CREATE INDEX
CREATE INDEX
— 创建通用审计触发器函数
CREATE OR REPLACE FUNCTION fgedu_generic_audit()
RETURNS TRIGGER
AS $$
BEGIN
IF TG_OP = ‘INSERT’ THEN
INSERT INTO fgedu_audit_log(
table_name,
operation_type,
row_id,
new_data
)
VALUES(
TG_TABLE_NAME,
TG_OP,
NEW.id,
to_jsonb(NEW)
);
RETURN NEW;
ELSIF TG_OP = ‘UPDATE’ THEN
INSERT INTO fgedu_audit_log(
table_name,
operation_type,
row_id,
old_data,
new_data
)
VALUES(
TG_TABLE_NAME,
TG_OP,
NEW.id,
to_jsonb(OLD),
to_jsonb(NEW)
);
RETURN NEW;
ELSIF TG_OP = ‘DELETE’ THEN
INSERT INTO fgedu_audit_log(
table_name,
operation_type,
row_id,
old_data
)
VALUES(
TG_TABLE_NAME,
TG_OP,
OLD.id,
to_jsonb(OLD)
);
RETURN OLD;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
— 输出结果
CREATE FUNCTION
— 为员工表添加审计触发器
CREATE TRIGGER trg_audit_employees
AFTER INSERT OR UPDATE OR DELETE ON fgedu_employees
FOR EACH ROW
EXECUTE FUNCTION fgedu_generic_audit();
— 输出结果
CREATE TRIGGER
— 测试审计触发器
UPDATE fgedu_employees SET salary = 12000.00 WHERE id = 1;
— 输出结果
UPDATE 1
— 查看审计日志
SELECT table_name, operation_type, row_id, old_data->>’salary’ AS old_salary, new_data->>’salary’ AS new_salary, operation_time
FROM fgedu_audit_log
WHERE table_name = ‘fgedu_employees’
ORDER BY operation_time DESC
LIMIT 5;
— 输出结果
table_name | operation_type | row_id | old_salary | new_salary | operation_time
————-+—————-+——–+————+————+————————
fgedu_employees | UPDATE | 1 | 9900.00 | 12000.00 | 2026-04-07 16:15:00
(1 row)
— 插入测试
INSERT INTO fgedu_employees(name, salary, department)
VALUES(‘郑十’, 10000.00, ‘技术部’);
— 输出结果
INSERT 0 1
— 查看审计日志
SELECT table_name, operation_type, row_id, new_data->>’name’ AS employee_name, operation_time
FROM fgedu_audit_log
WHERE table_name = ‘fgedu_employees’
ORDER BY operation_time DESC
LIMIT 5;
— 输出结果
table_name | operation_type | row_id | employee_name | operation_time
————-+—————-+——–+—————+————————
fgedu_employees | INSERT | 8 | 郑十 | 2026-04-07 16:20:00
fgedu_employees | UPDATE | 1 | 张三 | 2026-04-07 16:15:00
(2 rows)
4.2 PostgreSQL数据库数据校验触发器实战
本案例演示数据校验触发器的实现。更多学习教程公众号风哥教程itpux_com。
— 创建订单表
CREATE TABLE fgedu_orders (
id SERIAL PRIMARY KEY,
order_no VARCHAR(50) UNIQUE NOT NULL,
customer_id INTEGER NOT NULL,
amount NUMERIC(12,2) NOT NULL,
status VARCHAR(20) DEFAULT ‘pending’,
create_time TIMESTAMP DEFAULT NOW(),
update_time TIMESTAMP DEFAULT NOW()
);
— 输出结果
CREATE TABLE
— 创建校验触发器函数
CREATE OR REPLACE FUNCTION fgedu_order_validation()
RETURNS TRIGGER
AS $$
BEGIN
— 验证订单金额
IF NEW.amount <= 0 THEN
RAISE EXCEPTION 'Order amount must be greater than 0';
END IF;
-- 验证订单号格式
IF NEW.order_no !~ '^ORD[0-9]{8}$' THEN
RAISE EXCEPTION 'Order number must match format: ORDYYYYMMDD';
END IF;
-- 验证状态值
IF NEW.status NOT IN ('pending', 'paid', 'shipped', 'delivered', 'cancelled') THEN
RAISE EXCEPTION 'Invalid order status';
END IF;
-- 更新时间戳
NEW.update_time := NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 输出结果
CREATE FUNCTION
-- 创建校验触发器
CREATE TRIGGER trg_order_validation
BEFORE INSERT OR UPDATE ON fgedu_orders
FOR EACH ROW
EXECUTE FUNCTION fgedu_order_validation();
-- 输出结果
CREATE TRIGGER
-- 测试校验触发器(成功)
INSERT INTO fgedu_orders(order_no, customer_id, amount, status)
VALUES('ORD20260407', 1, 1000.00, 'pending');
-- 输出结果
INSERT 0 1
-- 测试校验触发器(失败:金额无效)
INSERT INTO fgedu_orders(order_no, customer_id, amount, status)
VALUES('ORD20260408', 2, -500.00, 'pending');
-- 输出结果
ERROR: Order amount must be greater than 0
-- 测试校验触发器(失败:订单号格式无效)
INSERT INTO fgedu_orders(order_no, customer_id, amount, status)
VALUES('ORDER20260407', 3, 1500.00, 'pending');
-- 输出结果
ERROR: Order number must match format: ORDYYYYMMDD
-- 测试校验触发器(失败:状态无效)
INSERT INTO fgedu_orders(order_no, customer_id, amount, status)
VALUES('ORD20260409', 4, 2000.00, 'invalid');
-- 输出结果
ERROR: Invalid order status
-- 测试更新操作
UPDATE fgedu_orders SET status = 'paid' WHERE id = 1;
-- 输出结果
UPDATE 1
-- 查看更新结果
SELECT * FROM fgedu_orders WHERE id = 1;
-- 输出结果
id | order_no | customer_id | amount | status | create_time | update_time
----+------------+-------------+--------+--------+----------------------+----------------------
1 | ORD20260407| 1 | 1000.00| paid | 2026-04-07 16:25:00 | 2026-04-07 16:30:00
(1 row)
4.3 PostgreSQL数据库数据同步触发器实战
本案例演示数据同步触发器的实现。from PostgreSQL视频:www.itpux.com。
— 创建主表
CREATE TABLE fgedu_customers (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
phone VARCHAR(20),
address TEXT,
create_time TIMESTAMP DEFAULT NOW(),
update_time TIMESTAMP DEFAULT NOW()
);
— 输出结果
CREATE TABLE
— 创建同步表(用于数据同步)
CREATE TABLE fgedu_customers_sync (
id SERIAL PRIMARY KEY,
customer_id INTEGER NOT NULL,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
sync_time TIMESTAMP DEFAULT NOW(),
sync_status VARCHAR(20) DEFAULT ‘pending’
);
— 输出结果
CREATE TABLE
— 创建同步触发器函数
CREATE OR REPLACE FUNCTION fgedu_customer_sync()
RETURNS TRIGGER
AS $$
BEGIN
IF TG_OP = ‘INSERT’ THEN
INSERT INTO fgedu_customers_sync(
customer_id,
name,
email
)
VALUES(
NEW.id,
NEW.name,
NEW.email
);
RETURN NEW;
ELSIF TG_OP = ‘UPDATE’ THEN
UPDATE fgedu_customers_sync
SET
name = NEW.name,
email = NEW.email,
sync_time = NOW(),
sync_status = ‘pending’
WHERE customer_id = NEW.id;
— 如果没有找到记录,插入新记录
IF NOT FOUND THEN
INSERT INTO fgedu_customers_sync(
customer_id,
name,
email
)
VALUES(
NEW.id,
NEW.name,
NEW.email
);
END IF;
RETURN NEW;
ELSIF TG_OP = ‘DELETE’ THEN
UPDATE fgedu_customers_sync
SET
sync_status = ‘deleted’,
sync_time = NOW()
WHERE customer_id = OLD.id;
RETURN OLD;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
— 输出结果
CREATE FUNCTION
— 创建同步触发器
CREATE TRIGGER trg_customer_sync
AFTER INSERT OR UPDATE OR DELETE ON fgedu_customers
FOR EACH ROW
EXECUTE FUNCTION fgedu_customer_sync();
— 输出结果
CREATE TRIGGER
— 测试同步触发器
INSERT INTO fgedu_customers(name, email, phone, address)
VALUES(‘张三’, ‘zhangsan@fgedu.net.cn’, ‘13800138000’, ‘北京市朝阳区’);
— 输出结果
INSERT 0 1
— 查看同步表
SELECT * FROM fgedu_customers_sync;
— 输出结果
id | customer_id | name | email | sync_time | sync_status
—-+————-+——+———————+———————-+————-
1 | 1 | 张三 | zhangsan@fgedu.net.cn| 2026-04-07 16:35:00 | pending
(1 row)
— 测试更新同步
UPDATE fgedu_customers SET email = ‘zhangsan_new@fgedu.net.cn’ WHERE id = 1;
— 输出结果
UPDATE 1
— 查看同步表
SELECT * FROM fgedu_customers_sync;
— 输出结果
id | customer_id | name | email | sync_time | sync_status
—-+————-+——+————————–+———————-+————-
1 | 1 | 张三 | zhangsan_new@fgedu.net.cn | 2026-04-07 16:40:00 | pending
(1 row)
— 测试删除同步
DELETE FROM fgedu_customers WHERE id = 1;
— 输出结果
DELETE 1
— 查看同步表
SELECT * FROM fgedu_customers_sync;
— 输出结果
id | customer_id | name | email | sync_time | sync_status
—-+————-+——+————————–+———————-+————-
1 | 1 | 张三 | zhangsan_new@fgedu.net.cn | 2026-04-07 16:45:00 | deleted
(1 row)
Part05-风哥经验总结与分享
5.1 PostgreSQL数据库触发器最佳实践
触发器最佳实践:合理选择触发器类型和时机;保持触发器逻辑简单;使用事务保证数据一致性;编写清晰的错误处理;定期维护触发器相关表;监控触发器执行性能。
- 数据验证:使用BEFORE行级触发器
- 数据审计:使用AFTER行级触发器
- 统计汇总:使用AFTER语句级触发器
- 数据同步:使用AFTER触发器
- 复杂约束:使用CONSTRAINT触发器
5.2 PostgreSQL数据库触发器常见问题
常见问题:性能问题、死锁、递归触发、权限问题、错误处理不当。
5.3 PostgreSQL数据库触发器调试技巧
调试技巧:使用RAISE NOTICE输出调试信息;使用日志记录触发器执行情况;使用事务回滚测试;分步测试触发器逻辑;检查触发器执行顺序。
— 创建带调试信息的触发器函数
CREATE OR REPLACE FUNCTION fgedu_debug_trigger()
RETURNS TRIGGER
AS $$
BEGIN
RAISE NOTICE ‘Trigger fired: % on %’, TG_OP, TG_TABLE_NAME;
RAISE NOTICE ‘Trigger level: %’, TG_LEVEL;
RAISE NOTICE ‘Trigger timing: %’, TG_WHEN;
IF TG_OP = ‘INSERT’ THEN
RAISE NOTICE ‘Inserting new row with id: %’, NEW.id;
ELSIF TG_OP = ‘UPDATE’ THEN
RAISE NOTICE ‘Updating row with id: %’, NEW.id;
ELSIF TG_OP = ‘DELETE’ THEN
RAISE NOTICE ‘Deleting row with id: %’, OLD.id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
— 输出结果
CREATE FUNCTION
— 创建调试触发器
CREATE TRIGGER trg_debug_employees
BEFORE INSERT OR UPDATE OR DELETE ON fgedu_employees
FOR EACH ROW
EXECUTE FUNCTION fgedu_debug_trigger();
— 输出结果
CREATE TRIGGER
— 测试调试触发器
UPDATE fgedu_employees SET salary = salary + 100 WHERE id = 2;
— 输出结果
NOTICE: Trigger fired: UPDATE on fgedu_employees
NOTICE: Trigger level: ROW
NOTICE: Trigger timing: BEFORE
NOTICE: Updating row with id: 2
UPDATE 1
— 查看日志
SELECT * FROM pg_log WHERE message LIKE ‘%Trigger fired%’ ORDER BY log_time DESC LIMIT 5;
— 输出结果
-[ RECORD 1 ]————————————————————————————————-
log_time | 2026-04-07 16:50:00.123456
user_name | fgedu
database_name | fgedudb
process_id | 12345
session_id | 54321
message | NOTICE: Trigger fired: UPDATE on fgedu_employees
-[ RECORD 2 ]————————————————————————————————-
log_time | 2026-04-07 16:50:00.123457
user_name | fgedu
database_name | fgedudb
process_id | 12345
session_id | 54321
message | NOTICE: Trigger level: ROW
-[ RECORD 3 ]————————————————————————————————-
log_time | 2026-04-07 16:50:00.123458
user_name | fgedu
database_name | fgedudb
process_id | 12345
session_id | 54321
message | NOTICE: Trigger timing: BEFORE
-[ RECORD 4 ]————————————————————————————————-
log_time | 2026-04-07 16:50:00.123459
user_name | fgedu
database_name | fgedudb
process_id | 12345
session_id | 54321
message | NOTICE: Updating row with id: 2
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
