yashandb教程FG021-YashanDB触发器使用场景
本文档风哥主要介绍YashanDB触发器的使用场景,包括YashanDB触发器的概念、类型、组成、创建、管理、监控以及生产环境中的实际应用案例,风哥教程参考YashanDB官方文档数据库开发手册内容,适合DBA和开发人员在学习和测试中使用。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 YashanDB触发器的概念
YashanDB触发器是一种特殊的存储过程,它在特定的数据库操作(如INSERT、UPDATE、DELETE)发生时自动执行。触发器可以用于实现数据审计、数据完整性约束、业务规则执行等功能。学习交流加群风哥微信: itpux-com
- 自动执行:不需要手动调用
- 响应事件:在特定操作发生时触发
- 可嵌套:触发器可以调用其他触发器
- 事务性:触发器操作是事务的一部分
- 安全性:可以实现复杂的安全控制
1.2 YashanDB触发器的类型
YashanDB支持以下类型的触发器:
– INSERT触发器:在执行INSERT操作时触发
– UPDATE触发器:在执行UPDATE操作时触发
– DELETE触发器:在执行DELETE操作时触发
# 按触发时机分类
– BEFORE触发器:在操作执行前触发
– AFTER触发器:在操作执行后触发
# 按作用范围分类
– 行级触发器:对每一行数据操作都触发
– 语句级触发器:对整个SQL语句只触发一次
# 特殊触发器
– INSTEAD OF触发器:用于视图,替代原有的操作
– 系统事件触发器:响应系统级事件
1.3 YashanDB触发器的组成
YashanDB触发器由以下部分组成:
- 触发器名称:唯一标识触发器
- 触发事件:INSERT、UPDATE、DELETE
- 触发时机:BEFORE、AFTER
- 触发级别:FOR EACH ROW(行级)或FOR EACH STATEMENT(语句级)
- 触发条件:WHEN子句,可选
- 触发器体:PL/SQL代码块
Part02-生产环境规划与建议
2.1 YashanDB触发器规划
在生产环境中使用YashanDB触发器时,需要进行以下规划:
– 明确触发器的业务需求
– 确定触发事件和时机
– 评估触发器的影响范围
# 触发器命名规范
– 采用有意义的命名
– 包含表名、操作类型、触发时机
– 例如:trg_emp_insert_after
# 触发器权限规划
– 确保触发器拥有必要的执行权限
– 避免使用SUPERUSER权限
# 触发器文档
– 记录触发器的功能、触发条件、执行逻辑
– 维护触发器的版本历史
2.2 YashanDB触发器性能考虑
YashanDB触发器的性能考虑:
- 触发器执行时间:复杂的触发器会增加操作响应时间
- 触发器嵌套:多层嵌套会导致性能下降
- 行级触发器:对大量数据操作时会执行多次
- 事务开销:触发器操作是事务的一部分,会增加事务开销
2.3 YashanDB触发器最佳实践
YashanDB触发器最佳实践:
- 保持简单:触发器逻辑应尽量简单
- 避免复杂操作:不要在触发器中执行复杂的业务逻辑
- 使用WHEN条件:减少不必要的触发
- 避免递归:防止触发器递归调用
- 监控性能:定期监控触发器的执行性能
- 测试充分:在测试环境充分测试触发器
Part03-生产环境项目实施方案
3.1 YashanDB触发器创建
3.1.1 YashanDB创建INSERT触发器
CREATE TABLE fgedu_employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(100),
salary NUMBER,
hire_date DATE,
last_update_date DATE
);
— 创建审计表
CREATE TABLE fgedu_employee_audit (
audit_id NUMBER PRIMARY KEY,
emp_id NUMBER,
operation VARCHAR2(20),
old_value VARCHAR2(4000),
new_value VARCHAR2(4000),
operation_date DATE,
operated_by VARCHAR2(100)
);
— 创建序列
CREATE SEQUENCE fgedu_audit_seq START WITH 1 INCREMENT BY 1;
— 创建INSERT触发器
CREATE OR REPLACE TRIGGER trg_fgedu_emp_insert_after
AFTER INSERT ON fgedu_employees
FOR EACH ROW
BEGIN
— 记录插入操作
INSERT INTO fgedu_employee_audit (
audit_id,
emp_id,
operation,
old_value,
new_value,
operation_date,
operated_by
) VALUES (
fgedu_audit_seq.NEXTVAL,
:NEW.emp_id,
‘INSERT’,
NULL,
‘Name: ‘ || :NEW.emp_name || ‘, Salary: ‘ || :NEW.salary,
SYSDATE,
USER
);
— 更新最后更新日期
UPDATE fgedu_employees
SET last_update_date = SYSDATE
WHERE emp_id = :NEW.emp_id;
END;
/
3.1.2 YashanDB创建UPDATE触发器
CREATE OR REPLACE TRIGGER trg_fgedu_emp_update_before
BEFORE UPDATE ON fgedu_employees
FOR EACH ROW
BEGIN
— 检查工资调整幅度
IF :NEW.salary > :OLD.salary * 1.5 THEN
RAISE_APPLICATION_ERROR(-20001, ‘工资调整幅度不能超过50%’);
END IF;
— 记录更新操作
INSERT INTO fgedu_employee_audit (
audit_id,
emp_id,
operation,
old_value,
new_value,
operation_date,
operated_by
) VALUES (
fgedu_audit_seq.NEXTVAL,
:OLD.emp_id,
‘UPDATE’,
‘Old salary: ‘ || :OLD.salary,
‘New salary: ‘ || :NEW.salary,
SYSDATE,
USER
);
— 更新最后更新日期
:NEW.last_update_date := SYSDATE;
END;
/
3.1.3 YashanDB创建DELETE触发器
CREATE OR REPLACE TRIGGER trg_fgedu_emp_delete_before
BEFORE DELETE ON fgedu_employees
FOR EACH ROW
BEGIN
— 记录删除操作
INSERT INTO fgedu_employee_audit (
audit_id,
emp_id,
operation,
old_value,
new_value,
operation_date,
operated_by
) VALUES (
fgedu_audit_seq.NEXTVAL,
:OLD.emp_id,
‘DELETE’,
‘Name: ‘ || :OLD.emp_name || ‘, Salary: ‘ || :OLD.salary,
NULL,
SYSDATE,
USER
);
END;
/
3.2 YashanDB触发器管理
3.2.1 YashanDB查看触发器
SELECT trigger_name, table_name, triggering_event, timing
FROM user_triggers;
— 查看触发器详细信息
SELECT * FROM user_triggers WHERE trigger_name = ‘TRG_FGEDU_EMP_INSERT_AFTER’;
— 查看触发器源代码
SELECT text FROM user_source WHERE name = ‘TRG_FGEDU_EMP_INSERT_AFTER’ ORDER BY line;
3.2.2 YashanDB启用/禁用触发器
ALTER TRIGGER trg_fgedu_emp_insert_after DISABLE;
— 启用触发器
ALTER TRIGGER trg_fgedu_emp_insert_after ENABLE;
— 禁用表上所有触发器
ALTER TABLE fgedu_employees DISABLE ALL TRIGGERS;
— 启用表上所有触发器
ALTER TABLE fgedu_employees ENABLE ALL TRIGGERS;
3.2.3 YashanDB删除触发器
DROP TRIGGER trg_fgedu_emp_insert_after;
3.3 YashanDB触发器监控
SELECT * FROM v$trigger_stats WHERE owner = ‘FGEDU’;
— 查看触发器相关的等待事件
SELECT * FROM v$session_wait WHERE event LIKE ‘%trigger%’;
— 查看最近执行的触发器
SELECT * FROM v$active_session_history WHERE program LIKE ‘%trigger%’;
Part04-生产案例与实战讲解
4.1 YashanDB触发器审计案例
在生产环境中,使用触发器实现数据审计功能:
INSERT INTO fgedu_employees (emp_id, emp_name, salary, hire_date)
VALUES (1, ‘张三’, 5000, SYSDATE);
— 执行结果
1 row created.
— 查看审计记录
SELECT * FROM fgedu_employee_audit WHERE emp_id = 1;
AUDIT_ID EMP_ID OPERATION OLD_VALUE NEW_VALUE OPERATION_DATE OPERATED_BY
———- ———- ——— ———- —————————- ——————– ———–
1 1 INSERT Name: 张三, Salary: 5000 2026-04-11 10:00:00 FGEDU
— 测试UPDATE操作
UPDATE fgedu_employees SET salary = 6000 WHERE emp_id = 1;
— 执行结果
1 row updated.
— 查看审计记录
SELECT * FROM fgedu_employee_audit WHERE emp_id = 1;
AUDIT_ID EMP_ID OPERATION OLD_VALUE NEW_VALUE OPERATION_DATE OPERATED_BY
———- ———- ——— —————— —————————- ——————– ———–
1 1 INSERT Name: 张三, Salary: 5000 2026-04-11 10:00:00 FGEDU
2 1 UPDATE Old salary: 5000 New salary: 6000 2026-04-11 10:01:00 FGEDU
— 测试DELETE操作
DELETE FROM fgedu_employees WHERE emp_id = 1;
— 执行结果
1 row deleted.
— 查看审计记录
SELECT * FROM fgedu_employee_audit WHERE emp_id = 1;
AUDIT_ID EMP_ID OPERATION OLD_VALUE NEW_VALUE OPERATION_DATE OPERATED_BY
———- ———- ——— —————————- ———- ——————– ———–
1 1 INSERT Name: 张三, Salary: 5000 2026-04-11 10:00:00 FGEDU
2 1 UPDATE Old salary: 5000 New salary: 6000 2026-04-11 10:01:00 FGEDU
3 1 DELETE Name: 张三, Salary: 6000 2026-04-11 10:02:00 FGEDU
4.2 YashanDB触发器数据完整性案例
使用触发器确保数据完整性:
CREATE TABLE fgedu_orders (
order_id NUMBER PRIMARY KEY,
customer_id NUMBER,
order_date DATE,
total_amount NUMBER
);
— 创建订单明细表
CREATE TABLE fgedu_order_items (
item_id NUMBER PRIMARY KEY,
order_id NUMBER REFERENCES fgedu_orders(order_id),
product_id NUMBER,
quantity NUMBER,
unit_price NUMBER,
item_amount NUMBER
);
— 创建触发器确保订单总金额正确
CREATE OR REPLACE TRIGGER trg_fgedu_order_items_after
AFTER INSERT OR UPDATE OR DELETE ON fgedu_order_items
FOR EACH ROW
DECLARE
v_total NUMBER;
BEGIN
— 重新计算订单总金额
SELECT SUM(item_amount) INTO v_total
FROM fgedu_order_items
WHERE order_id = NVL(:NEW.order_id, :OLD.order_id);
— 更新订单表
UPDATE fgedu_orders
SET total_amount = NVL(v_total, 0)
WHERE order_id = NVL(:NEW.order_id, :OLD.order_id);
END;
/
— 测试数据
INSERT INTO fgedu_orders (order_id, customer_id, order_date) VALUES (1, 101, SYSDATE);
INSERT INTO fgedu_order_items (item_id, order_id, product_id, quantity, unit_price, item_amount) VALUES (1, 1, 201, 2, 100, 200);
INSERT INTO fgedu_order_items (item_id, order_id, product_id, quantity, unit_price, item_amount) VALUES (2, 1, 202, 1, 150, 150);
— 查看订单总金额
SELECT order_id, total_amount FROM fgedu_orders WHERE order_id = 1;
ORDER_ID TOTAL_AMOUNT
———- ————
1 350
— 更新订单明细
UPDATE fgedu_order_items SET quantity = 3 WHERE item_id = 1;
UPDATE fgedu_order_items SET item_amount = 300 WHERE item_id = 1;
— 查看订单总金额
SELECT order_id, total_amount FROM fgedu_orders WHERE order_id = 1;
ORDER_ID TOTAL_AMOUNT
———- ————
1 450
— 删除订单明细
DELETE FROM fgedu_order_items WHERE item_id = 2;
— 查看订单总金额
SELECT order_id, total_amount FROM fgedu_orders WHERE order_id = 1;
ORDER_ID TOTAL_AMOUNT
———- ————
1 300
4.3 YashanDB触发器日志记录案例
使用触发器记录重要操作日志:
CREATE TABLE fgedu_operation_logs (
log_id NUMBER PRIMARY KEY,
operation_type VARCHAR2(50),
operation_table VARCHAR2(50),
operation_details VARCHAR2(4000),
operation_date DATE,
operator VARCHAR2(100),
ip_address VARCHAR2(50)
);
— 创建日志序列
CREATE SEQUENCE fgedu_log_seq START WITH 1 INCREMENT BY 1;
— 创建通用操作日志触发器
CREATE OR REPLACE TRIGGER trg_fgedu_logging
AFTER INSERT OR UPDATE OR DELETE ON fgedu_employees
FOR EACH ROW
DECLARE
v_operation VARCHAR2(20);
v_details VARCHAR2(4000);
BEGIN
— 确定操作类型
IF INSERTING THEN
v_operation := ‘INSERT’;
v_details := ‘插入员工: ‘ || :NEW.emp_name;
ELSIF UPDATING THEN
v_operation := ‘UPDATE’;
v_details := ‘更新员工: ‘ || :OLD.emp_name;
ELSIF DELETING THEN
v_operation := ‘DELETE’;
v_details := ‘删除员工: ‘ || :OLD.emp_name;
END IF;
— 插入日志
INSERT INTO fgedu_operation_logs (
log_id,
operation_type,
operation_table,
operation_details,
operation_date,
operator,
ip_address
) VALUES (
fgedu_log_seq.NEXTVAL,
v_operation,
‘FGEDU_EMPLOYEES’,
v_details,
SYSDATE,
USER,
SYS_CONTEXT(‘USERENV’, ‘IP_ADDRESS’)
);
END;
/
— 测试操作
INSERT INTO fgedu_employees (emp_id, emp_name, salary, hire_date)
VALUES (2, ‘李四’, 6000, SYSDATE);
— 查看日志
SELECT * FROM fgedu_operation_logs;
LOG_ID OPERATION_TYPE OPERATION_TABLE OPERATION_DETAILS OPERATION_DATE OPERATOR IP_ADDRESS
—— ————– ————— ———————- ——————– ———- —————
1 INSERT FGEDU_EMPLOYEES 插入员工: 李四 2026-04-11 10:05:00 FGEDU 192.168.1.100
Part05-风哥经验总结与分享
5.1 YashanDB触发器使用经验
YashanDB触发器使用经验总结:
- 适用场景:数据审计、数据完整性、简单的业务规则
- 不适用场景:复杂业务逻辑、大量数据操作、高并发场景
- 性能考虑:尽量减少触发器中的复杂操作,使用WHEN条件过滤
- 维护考虑:定期检查和清理不必要的触发器
- 测试考虑:在测试环境充分测试触发器的功能和性能
5.2 YashanDB触发器故障排除
## 1. 触发器执行失败
– 症状:操作时报错,提示触发器执行失败
– 原因:触发器代码有语法错误或逻辑错误
– 解决:检查触发器代码,修复错误
## 2. 触发器导致性能下降
– 症状:操作响应时间变长
– 原因:触发器执行时间过长
– 解决:优化触发器代码,减少复杂操作
## 3. 触发器递归调用
– 症状:系统挂起或报错
– 原因:触发器中执行了会再次触发自身的操作
– 解决:修改触发器逻辑,避免递归
## 4. 触发器权限问题
– 症状:触发器执行时报权限错误
– 原因:触发器没有必要的执行权限
– 解决:授予触发器必要的权限
## 5. 触发器数据不一致
– 症状:数据与预期不符
– 原因:触发器逻辑错误或事务回滚
– 解决:检查触发器逻辑,确保事务一致性
5.3 YashanDB触发器使用建议
YashanDB触发器使用建议:
- 谨慎使用:只在必要的场景下使用触发器
- 保持简单:触发器逻辑应尽量简单
- 充分测试:在测试环境测试触发器的功能和性能
- 监控性能:定期监控触发器的执行情况
- 文档化:记录触发器的功能和维护历史
- 版本控制:对触发器代码进行版本控制
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
