在触发器里面commit

Normally, the usage of a commit or a rollback is not recommended in triggers.  But there are certain situations in which we have to use commit or rollback in triggers.  One of the prevalent usages of commit in trigger is to avoid the mutating table error encountered during trigger execution prior to 11g. Other way to avoid this error is use of compound trigger introduced in Oracle 11g. We will cover mutating trigger in a different blog post…today we will show how can we use commit/rollback in triggers.


To use database control statements in triggers, we have to use compiler directive ‘pragma autonomous_transaction’.When we define trigger as autonomous, it becomes independent and does not belong to current transaction. Since trigger is not part of current transaction, use of commit is allowed in the trigger when declared with pragma. This holds true for any package, procedure and/or function defined with pragma directive. Let us start with an example. We will create two tables and trigger to explain the scenario. Example is based on the one mentioned in oracle documentation.

CREATE TABLE TEST
(
COL1 NUMBER(9) PRIMARY KEY,
COL2 VARCHAR2(30),
COL3 NUMBER(5)
);


CREATE TABLE AUDIT_TEST
(
COL1 NUMBER(9),
COL2 VARCHAR2(30),
OLD_COL3 NUMBER(5),
NEW_COL3 NUMBER(5),
COL4 DATE
);


INSERT INTO TEST
SELECT rownum,’HELLO..’||to_char(rownum), rownum*1000
FROM user_Tables;

Now create following trigger with commit statement in the trigger body.
CREATE OR REPLACE TRIGGER TUA_TEST
AFTER UPDATE OF COL3
ON TEST
FOR EACH ROW
BEGIN
INSERT INTO audit_test(col1,col2,new_col3,old_col3,col4)
VALUES(: old.col1, : old.col2, : new.col3, : old.col3,sysdate);
COMMIT;
END;
/
Trigger will get created without any error. But whenever we update test table, we run into following error.

SQL> UPDATE TEST
2  SET COL3 = 2000
3  WHERE col1 = 1;
UPDATE TEST
*
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at “SCOTT.TUA_TEST”, line 5
ORA-04088: error during execution of trigger ‘SCOTT.TUA_TEST’


Now let us create same trigger with pragma autonomous_transaction and execute the update statement again.
CREATE OR REPLACE TRIGGER TUA_TEST
AFTER UPDATE OF COL3
ON TEST
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO audit_test(col1,col2,new_col3,old_col3,col4)
VALUES(: old.col1, : old.col2, :new.col3, : old.col3,sysdate);

COMMIT;

END;
/

/* update statement*/
SQL> update test
2  set col3 = 2000
3  where col1 = 1;

1 row updated.

This time update went through fine since trigger is declared autonomous As mentioned earlier, it is not a routine requirement to use control statements in triggers but under certain scenarios where we have to use control statements, this is the way to use it.

转载自:

http://decipherinfosys.wordpress.com/2009/03/31/using-commit-and-rollback-in-triggers/




<think>好的,我需要向用户介绍Oracle数据库中的触发器怎么使用。首先,我得回忆一下触发器的基本概念和用途。触发器是一种特殊的存储过程,当特定的事件在数据库表上发生时自动执行。常见的事件包括INSERT、UPDATE、DELETE等DML操作,还有DDL操作和数据库事件如启动或关闭。 接下来,用户可能想知道触发器的类型。需要分清楚行级触发器和语句级触发器。行级触发器会对每一行受影响的数据执行一次,而语句级触发器则在每次SQL语句执行时触发一次。此外,还有BEFORE和AFTER触发器的区别,分别是在事件发生之前或之后执行。 然后,我需要解释如何创建触发器。基本的语法结构是CREATE TRIGGER,后面跟着触发器名称、触发时机(BEFORE/AFTER)、事件(INSERT等)、ON表名,以及触发器的类型(FOR EACH ROW如果是行级)。然后是触发器体,里面包含PL/SQL代码。 用户可能还需要具体的例子来理解。比如,可以举一个在插入新记录前自动生成主键的例子,或者更新数据时记录日志的案例。这些例子应该展示BEFORE INSERT和AFTER UPDATE触发器的应用。 另外,要注意触发器的限制和注意事项。例如,触发器内部不能使用COMMIT或ROLLBACK,因为它们是在事务中执行的。还有,过多的触发器可能会影响性能,需要谨慎使用。 可能还需要提到触发器的管理,比如查看、修改、禁用和删除触发器。相关的数据字典视图如USER_TRIGGERS,以及ALTER TRIGGER和DROP TRIGGER命令。 最后,确保按照用户的要求使用正确的中文术语,LaTeX公式的格式正确,特别是行内公式用$...$,独立公式用$$...$$,并且结构清晰,分步骤说明。同时,保持口语化,避免使用过于技术性的术语,但又要准确无误。 需要检查是否有遗漏的部分,比如触发器的条件WHEN子句,或者引用新旧数据的方式(:OLD和:NEW)。确保这些细节都被涵盖,以提供全面的信息。同时,提醒用户在实际应用中测试触发器,避免逻辑错误。</think>Oracle数据库中的触发器Trigger)是一种与表相关联的存储程序,**当特定事件(如INSERT/UPDATE/DELETE)发生时自动执行**。以下是详细的使用指南: --- ### 一、触发器的核心组成 1. **触发时机** - `BEFORE`:在事件**执行前**触发(常用于数据校验或修改) - `AFTER`:在事件**执行后**触发(常用于记录日志) - `INSTEAD OF`:替代原操作(主要用于视图) 2. **触发事件** - **DML事件**:`INSERT`、`UPDATE`、`DELETE` - **DDL事件**:`CREATE`、`ALTER`、`DROP` - **数据库事件**:登录/注销、服务器错误等 3. **粒度类型** - **行级触发器**(`FOR EACH ROW`):每影响一行数据触发一次(通过`:OLD`和`:NEW`访问旧/新值) - **语句级触发器**:每条SQL语句触发一次(默认类型) --- ### 二、创建触发器的基本语法 ```sql CREATE [OR REPLACE] TRIGGER 触发器名称 [BEFORE | AFTER | INSTEAD OF] 触发事件1 [OR 触发事件2 ...] ON 表名或视图名 [FOR EACH ROW] -- 指定行级触发器 [WHEN (条件)] -- 可选:触发条件 DECLARE -- 变量声明(可选) BEGIN -- 逻辑代码(例如:修改数据、记录日志等) END; ``` --- ### 三、经典示例 #### 示例1:BEFORE INSERT触发器(自动生成主键) ```sql CREATE OR REPLACE TRIGGER trg_auto_id BEFORE INSERT ON employees FOR EACH ROW BEGIN -- 使用序列生成主键 SELECT employee_seq.NEXTVAL INTO :NEW.employee_id FROM dual; END; ``` #### 示例2:AFTER UPDATE触发器(记录修改日志) ```sql CREATE OR REPLACE TRIGGER trg_log_salary_change AFTER UPDATE OF salary ON employees FOR EACH ROW WHEN (OLD.salary != NEW.salary) -- 仅当薪资变化时触发 BEGIN INSERT INTO salary_log (employee_id, old_salary, new_salary, change_date) VALUES (:OLD.employee_id, :OLD.salary, :NEW.salary, SYSDATE); END; ``` --- ### 四、关键注意事项 1. **`:OLD`和`:NEW`的用法** - **INSERT**:仅可使用`:NEW` - **UPDATE**:可使用`:OLD`(旧值)和`:NEW`(新值) - **DELETE**:仅可使用`:OLD` 2. **避免递归触发** 若触发器A修改表T,而表T上还有其他触发器B,需确保逻辑不形成无限循环。 3. **性能影响** 行级触发器对批量操作性能影响较大,需谨慎设计。 --- ### 五、管理触发器 - **查看触发器**: ```sql SELECT * FROM USER_TRIGGERS WHERE TRIGGER_NAME = '触发器名称'; ``` - **启用/禁用**: ```sql ALTER TRIGGER 触发器名称 DISABLE; -- 禁用 ALTER TRIGGER 触发器名称 ENABLE; -- 启用 ``` - **删除触发器**: ```sql DROP TRIGGER 触发器名称; ``` --- ### 六、适用场景 1. 数据完整性校验(如禁止负数金额) 2. 审计跟踪(记录关键字段修改) 3. 级联操作(如删除主表时同步删除子表) 4. 业务规则自动化(如计算衍生字段) 合理使用触发器可以简化应用层逻辑,但需注意维护复杂度和性能影响 ✅。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值