【问题标题】:ora-01403 no data found error,ora-04088 error during execution of triggerora-01403 no data found error,ora-04088 执行触发器时出错
【发布时间】:2014-04-30 14:21:51
【问题描述】:

嗨,我有这个触发器

create or replace TRIGGER trg_cust
after insert or update on nbty_customer
referencing old as old new as new
for each row
declare
pragma autonomous_transaction;
V_REQ VARCHAR2(10);
begin 

 IF(:NEW.cust_sal<1000)
        THEN
        select :NEW.cust_sal+:OLD.cust_sal INTO V_REQ FROM nbty_customer
        where cust_id=:old.cust_id;

    ELSE
    SELECT :NEW.cust_sal-:OLD.cust_sal INTO V_REQ FROM nbty_customer where cust_id=:old.cust_id;
    end if;

merge into nbty_cache_cust 
    using
       (select distinct :new.cust_id cust_id, :new.cust_name cust_name,V_REQ V_REQ
       from nbty_customer) b
       on (cust_nbty_id = b.cust_id)
        when matched then
       update set cust_nbty_name = b.cust_name, cust_nbty_sal = b.V_REQ 
       when not matched then
      insert (cust_nbty_id, cust_nbty_name, cust_nbty_sal)
      values (b.cust_id, b.cust_name, b.V_REQ);
      commit;
      end;

哪个编译正确,但是当在表 nbty_customer 上完成插入时,例如

insert into nbty_customer values('2','abc','200')

在执行触发器时抛出 ora-01403 no data found 错误,ora-04088 错误 请帮忙,我无法弄清楚问题是什么?

【问题讨论】:

  • 没有数据我们无法判断。事实是,有一个 select 没有产生任何结果,你没有抓住。

标签: oracle plsql


【解决方案1】:

问题是由于 select into 子句返回“未找到数据”,因此我删除了 select into 并直接使用绑定变量:

IF(:new.cust_sal<1000)
then
  v_req:=nvl(:new.cust_sal,0)+nvl(:old.cust_sal,0);
else
  v_req:=nvl(:new.cust_sal,0)-nvl(:old.cust_sal,0);
end if;

这解决了问题。

【讨论】:

    【解决方案2】:

    我刚刚评论了,然后我注意到了:

    select :NEW.cust_sal+:OLD.cust_sal INTO V_REQ FROM nbty_customer
        where cust_id=:old.cust_id;
    

    在insert 上,这个select 将失败,因为没有:old.cust_id。请改用:new.cust_id。 (另外,:old.cust_sal 也将为空)

    【讨论】:

    • 是的,我用过 :new.cust_id 仍然抛出同样的错误,抱歉这么晚才回复
    • 我尝试使用 select nvl(:NEW.cust_sal,0)+nvl(:OLD.cust_sal,0) INTO V_REQ FROM nbty_customer where cust_id=:new.cust_id;但无济于事,它仍然抛出同样的错误,请帮助
    • 能否在问题中添加完整的插入语句,包括列名?
    • 插入 nbty_customer(cust_id,cust_name,cust_sal) 值 ('111','abc,'1000');
    • 这将进入无效的 else 分支。那时还没有客户。
    【解决方案3】:

    在您的触发器正文中,您正在尝试选择新行的数据:

     SELECT :NEW.cust_sal-:OLD.cust_sal INTO V_REQ FROM nbty_customer where cust_id=:old.cust_id;
    

    但是您将触发器主体声明为PRAGMA AUTONOMOUS_TRANSACTION。因此,您的触发器首先看不到触发触发器执行的更改。

    在触发器中使用AUTONOMOUS_TRANSACTION从不是个好主意;请参阅Tom Kyte on Triggers,详细了解为什么要避免这种情况。

    如果您出于性能原因需要缓存数据,我建议您改用物化视图。如果需要,您可以将其设置为REFRESH ON COMMIT:

    create materialized view mv_cache
    refresh on commit 
    as 
    select distinct cust_id cust_id, cust_name cust_name, V_REQ 
    from nbty_customer
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-29
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 2022-01-20
      • 2013-10-14
      相关资源
      最近更新 更多