自治事务触发器问题解答

 
环境:
一个数据库下有两个用户一个为smis一个为yz,yz用户只有查询smis用户表的权限。所有的操作都在smis用户下,使用的数据库为Oracle9i。
在smis用户下有表:
create table SONG_TEST
(
 ZXZT CHAR( 1),
 ID   VARCHAR2(10)
)
yz 用户下有表:
create table T_SONG_TEST
(
 ZXZT CHAR( 2),
 ID   VARCHAR2(10)
)
yz 用户下有触发器:
create or replace trigger TRI_SONG_IN
     after insert on smis.SONG_TEST 
    for each row
declare
begin
insert into t_song_test(id,song)values(:new.id, :new.zxzt);
end TRI_SONG_IN;
1              为什么在smis用户下插入数据时没有提交而yz用户表中却有数据?
这是因为在目录的触发器中使用的是自治事务触发器,这种触发器使得触发的操作和目录的操作不在同一个事物中。
经过测试没有使用自治事务在没有提交数据前,对比表中没有数据。而使用了自治事务触发器则在没有提交数据前,yz用户表中已经存在了数据。
自治事物触发器的声明为,在declare内加入:
pragma    autonomous_transaction;
触发器为:
create or replace trigger TRI_SONG_IN
     after insert on smis.SONG_TEST 
    for each row
declare
pragma    autonomous_transaction;
begin
insert into t_song_test(id,song) values(: new.id, : new.zxzt);
commit;
end TRI_SONG_IN;
2              如果smis用户的zxzt字段小于yz用户表中的zxzt字段,能插进去数据吗?
经过测试smis用户的zxzt字段为char(5),而yz用户表中的zxzt字段为char(1),在这种情况下插入数据,
例如:
insert into song_test(id,zxzt)values('1','22222')
则出现的结果是:
ORA-01401: 插入的值对于列过大
ORA-06512: 在"YZ.TRI_SONG_IN", line 5
ORA-04088: 触发器 'YZ.TRI_SONG_IN' 执行过程中出错
这样在smis用户和yz用户表中都没有插入数据。因为触发器出错会向上抛出异常,最后由PL/SQL处理,将整个事物回滚。
3              如果用自治事物触发器去查找临时表中的数据,然后插入yz用户表。如果没有查找到数据会怎样?
经过测试如果没有找到数据则会出现以下信息:
ORA-01403: 未找到数据
ORA-06512: 在"YZ.TRI_CQZ_GJHZW_IN", line 6
ORA-04088: 触发器 'YZ.TRI_CQZ_GJHZW_IN' 执行过程中出错
这样其所做的操作也一起回滚。因为触发器出错会向上抛出异常,最后由PL/SQL处理,将整个事物回滚。
4              触发器中的变量如果定义过大,会怎样?
触发器写法如下:
create or replace trigger TRI_SONG_IN
    after insert on smis.SONG_TEST 
    for each row
    declare
   str char(10);
   pragma   autonomous_transaction;
    begin
    str:='1';
    insert into t_song_test(id,zxzt)values(:new.id,str);
    commit;
    end TRI_SONG_IN;
其中zxzt的字段大小为char(2),执行以下操作:
insert into song_test(id,zxzt)values('1','2')
则会出现以下信息:
ORA-01401: 插入的值对于列过大
ORA-06512: 在"YZ.TRI_SONG_IN", line 7
ORA-04088: 触发器 'YZ.TRI_SONG_IN' 执行过程中出错
这时smis中的表和对比表中都没有数据。因为触发器出错会向上抛出异常,最后由PL/SQL处理,将整个事物回滚。
5              自治事务触发器和相对应的操作是否在一个事物中?
在第四问中大家将要问到为什么smis表中都没有数据,他们的事务不是分开的吗?
我们现在来改写以下触发器:
create or replace trigger TRI_SONG_IN
    after insert on smis.SONG_TEST 
    for each row
    declare
   str char(10);
   pragma   autonomous_transaction;
    begin
    str:='1';
    insert into t_song_test(id,zxzt)values(:new.id,str);
    commit;
exception
   when others then
   rollback;
   end TRI_SONG_IN;
在这里我们加入了对异常的捕获和处理然后在执行插入操作:
insert into song_test(id,zxzt)values('1','2')
并提交,这样则会正确执行。而且smis的表中也有相应的数据插入。但在yz用户表中却没有数据。通过分析得知原来是异常惹得祸,在触发器中如果没有捕获和处理异常,触发器就会在运行时自动抛出, 执行部分抛出的异常将首先传递到同一块的异常部分,如果在同一块的异常部分没有处理这个异常的处理器,那么异常将会传播到上一层的异常部分中,一直到最外层。当异常到最外层时 PL/SQL 就将整个事务回滚。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值