Plsql ORA-04091:表******正在变异,触发器/函数可能看不到它

Plsql ORA-04091:表******正在变异,触发器/函数可能看不到它,plsql,Plsql,我有以下错误: ORA-04091:table SYSTEM.ORDINE正在发生变异,触发器/函数可能不存在 看到了吗 在此触发器PL/SQL上: create or replace trigger T_Ordine after insert on Ordine for each row DECLARE conta number := 0; t_o exception; BEGIN select count(*) into conta from Cliente join Ordine on

我有以下错误:

ORA-04091:table SYSTEM.ORDINE正在发生变异,触发器/函数可能不存在 看到了吗

在此触发器PL/SQL上:

create or replace trigger T_Ordine
after insert on Ordine
for each row

DECLARE
conta number := 0;
t_o exception;

BEGIN
select count(*) into conta
from Cliente join Ordine on Cliente.ID_Cliente = Ordine.ID_CLiente
where Cliente.C_CF_Rivenditore <> Ordine.CF_Rivenditore;

if conta > 0 then
raise t_o;
end if;

EXCEPTION
when t_o then
raise_application_error(-20002,'Un rivenditore non puo ricevere ordini da un cliente non suo');
end;
/
创建或替换触发器命令
在Ordine上插入后
每行
声明
conta数:=0;
例外情况;
开始
选择count(*)进入conta
从Cliente加入Cliente.ID_Cliente=Ordine.ID_Cliente上的Ordine
其中Cliente.C_CF_rivenditor或line.CF_rivenditor;
如果conta>0,则
提高t_o;
如果结束;
例外情况
那你什么时候去
提出申请错误(-20002,'Un RIVENDITOR non puo ricevere ordini da Un CLIENT non suo');
结束;
/

我认为在与table
Cliente
的连接中修改table
Ordine
所导致的错误有点奇怪

您已经为每一行声明了
,但从未使用
:new
访问任何插入的值

据我所知,有两种方法可以修复触发器:

  • 将触发器设为语句级触发器,以便在插入
    ordine
    表后运行一次,而不管插入了多少行。要执行此操作,只需删除每行的行

  • 调整触发器以仅检查插入的顺序,而不是检查表中的每个顺序。为此,请将用于查找
    conta
    的SQL查询替换为以下内容:

    select count(*) into conta
    from Cliente 
    where Cliente.ID_Cliente = :new.ID_CLiente
    and Cliente.C_CF_Rivenditore <> :new.CF_Rivenditore;
    

    你的扳机有点怪

    您已经为每一行声明了
    ,但从未使用
    :new
    访问任何插入的值

    据我所知,有两种方法可以修复触发器:

  • 将触发器设为语句级触发器,以便在插入
    ordine
    表后运行一次,而不管插入了多少行。要执行此操作,只需删除每行的行

  • 调整触发器以仅检查插入的顺序,而不是检查表中的每个顺序。为此,请将用于查找
    conta
    的SQL查询替换为以下内容:

    select count(*) into conta
    from Cliente 
    where Cliente.ID_Cliente = :new.ID_CLiente
    and Cliente.C_CF_Rivenditore <> :new.CF_Rivenditore;
    

    你的扳机有点怪

    您已经为每一行声明了
    ,但从未使用
    :new
    访问任何插入的值

    据我所知,有两种方法可以修复触发器:

  • 将触发器设为语句级触发器,以便在插入
    ordine
    表后运行一次,而不管插入了多少行。要执行此操作,只需删除每行的行

  • 调整触发器以仅检查插入的顺序,而不是检查表中的每个顺序。为此,请将用于查找
    conta
    的SQL查询替换为以下内容:

    select count(*) into conta
    from Cliente 
    where Cliente.ID_Cliente = :new.ID_CLiente
    and Cliente.C_CF_Rivenditore <> :new.CF_Rivenditore;
    

    你的扳机有点怪

    您已经为每一行声明了
    ,但从未使用
    :new
    访问任何插入的值

    据我所知,有两种方法可以修复触发器:

  • 将触发器设为语句级触发器,以便在插入
    ordine
    表后运行一次,而不管插入了多少行。要执行此操作,只需删除每行的行

  • 调整触发器以仅检查插入的顺序,而不是检查表中的每个顺序。为此,请将用于查找
    conta
    的SQL查询替换为以下内容:

    select count(*) into conta
    from Cliente 
    where Cliente.ID_Cliente = :new.ID_CLiente
    and Cliente.C_CF_Rivenditore <> :new.CF_Rivenditore;
    

    因为我是意大利人,所以我在理解您的意图方面有一点优势:

  • “Ordine”是订单表(与产品订单类似)
  • “Rivenditor”是指“卖方”
  • “客户”是指客户
  • 在“客户”表中,有一个字段(C_CF_rivenditor)强制要求卖方将其用于客户发出的订单
  • “订单”表包含对客户和收到订单的卖方的引用
  • 您只是想使插入不同于为每个客户指定的卖家的订单变得不可能(这是您的错误消息所说的),但您不知道如何使用:new或:old,因此您以这种方式编写了测试(这根本不是最好的方法,因为每次插入新订单时都要重新检查表中的所有订单)

    这就是你真正想写的:

          create or replace trigger T_Ordine
           after insert on Ordine
           for each row
    
          DECLARE
            rivenditore_del_cliente  Cliente.C_CF_Rivenditore%type;
    
          BEGIN
           select  Cliente.C_CF_Rivenditore
             into  rivenditore_del_cliente
             from Cliente
            where Cliente.ID_Cliente = :new.ID_CLiente
    
            if rivenditore_del_cliente <> :new.CF_Rivenditore  then
                raise raise_application_error(-20002,
                             'Un rivenditore non puo ricevere ordini da un cliente non suo');
            end if;  
          end;
    
    创建或替换触发器命令
    在Ordine上插入后
    每行
    声明
    Rivenditor_del_cliente cliente.C_CF_Rivenditor%类型;
    开始
    选择Cliente.C\u CF\u rivenditor
    进入Rivenditor_del_客户
    来自客户
    其中Cliente.ID\u Cliente=:new.ID\u Cliente
    如果rivenditor\u del\u客户:new.CF\u rivenditor则
    raise_应用程序_错误(-20002,
    “不提供价格或服务的客户不提供价格”);
    如果结束;
    结束;
    
    如果其中一些是真的,则可能需要通过进一步检查扩展上述触发器:

  • id_cliente不是“cliente”的主键
  • ordine.id_客户不是强制性的
  • 没有确保ordine.id_cliente是clienti表的有效id_cliente的外键约束

  • 因为我是意大利人,所以我在理解您的意图方面有一点优势:

  • “Ordine”是订单表(与产品订单类似)
  • “Rivenditor”是指“卖方”
  • “客户”是指客户
  • 在“客户”表中,有一个字段(C_CF_rivenditor)强制要求卖方将其用于客户发出的订单
  • “订单”表包含对客户和收到订单的卖方的引用
  • 您只是想让卖家无法插入与为每个客户指定的订单不同的订单(这是您的错误消息所说的),但您不知道如何使用:new或:old,