Oracle触发器在插入和更新时检查值

问题描述 投票:1回答:2

我正在尝试检查是否存在彼此交叉的价值差距。让我快速解释一下。

记录1:公司AA:距离差距-> 100-200建议2:公司AA:距离差距-> 200-300有效Rec 3:公司AA:间距-> 250-450无效Rec 4:公司JL:间距-> 250-450有效

记录3无效,因为它在记录2的距离值之间。Rec 4有效,因为公司与众不同

因此我写了一个触发器来防止它。

create or replace trigger ab_redemption_billing_mpr
  after insert or update on redemption_billing_mpr
  for each row
declare
  v_is_distance_range_valid boolean;
begin
  v_is_distance_range_valid := p_redemption_billing.is_distance_range_valid(:new.id,
                                                                            :new.redemption_billing_company,
                                                                            :new.distance_min,
                                                                            :new.distance_max,
                                                                            'redemption_billing_mpr');
  if not v_is_distance_range_valid then
    raise_application_error(-20001, 'This is a custom error');
  end if;
end ab_redemption_billing_mpr;

功能:

function is_distance_range_valid(p_id           in number,
                                   p_company      in varchar2,
                                   p_distance_min in number,
                                   p_distance_max in number,
                                   p_table_name   in varchar2) return boolean is
    d_record_number number;
  begin
    execute immediate 'select count(*) from ' || p_table_name || ' r 

        where r.redemption_billing_company = :1 
        and (:2 between r.distance_min and r.distance_max or :3 between r.distance_min and r.distance_max)
        and r.id = nvl(:4, id)'
      into d_record_number
      using p_company, p_distance_min, p_distance_max, p_id;
    if (d_record_number > 0) then
      return false;
    else
      return true;
    end if;
  end;

is_distance_range_valid()可以正常工作。如果返回false,则表示范围检查无效,并且请勿插入或更新。

[当我创建场景以捕获此异常时,oracle提供

ORA-04091:表名正在更改,触发器/函数可能看不到它

并且当我单击调试按钮时,它指向选择count(*)行。

我不知道为什么会收到此错误。预先感谢。

oracle plsql dynamic-sql database-trigger
2个回答
1
投票

只需检查以下方法是否可以解决您的问题

[创建具有查找is_distance_range_valid验证所需的列的日志表,并在触发器中插入此日志选项卡。主表上的触发器必须为插入或更新触发器之前] >>

在此日志表上创建触发器,并在日志表触发器中进行验证并引发错误。日志表上的触发器必须为在插入或更新触发器之后>]。

此外,仅当主表中已存在该行且该行不属于当前插入或更新的一部分时,此方法才起作用。如果需要验证当前插入或更新,那么我们需要使用:new.column_name进行验证

测试:-

    create table t_trg( n number);

    create table t_trg_log( n number);


    create or replace trigger trg_t
    before insert or update on t_trg
      for each row
    declare
    l_cnt number;
    begin
    insert into t_trg_log values(:new.n);
    end trg_t;

    create or replace trigger trg_t_log
      after insert or update on t_trg_log
      for each row
    declare
    l_cnt number;
    begin
    select count(1) into l_cnt from t_trg
    where n=:new.n;

    if  l_cnt  > 0  then
        raise_application_error(-20001, 'This is a custom error');
      end if;

    end trg_t_log;

我第一次插入它不会引发错误

  insert into t_trg values(7);

  1 row inserted.

第二次执行时,出现自定义错误

   insert into t_trg values(7);

  Error report -
  ORA-20001: This is a custom error
  ORA-06512: at "TRG_T_LOG", line 7
  ORA-04088: error during execution of trigger 'TRG_T_LOG'
  ORA-06512: at "TRG_T", line 4
  ORA-04088: error during execution of trigger 'TRG_T'

Update

:-使用复合触发器会在第一次完成插入时引发错误,因为它还会考虑在执行SELECT时我们正在更新或插入的当前行。

首先,我要感谢psaraj12的努力。

我找到了解决方案。 Oracle强迫我们不要在每一行之前使用选择查询。Oracle trigger error ORA-04091

所以我写了这个,它起作用了。

create or replace trigger ab_redemption_billing_mpr
  for insert or update on redemption_billing_mpr
  compound trigger

  v_is_distance_range_valid  boolean;
  id                         redemption_billing_mpr.id%type;
  redemption_billing_company redemption_billing_mpr.redemption_billing_company%type;
  distance_min               redemption_billing_mpr.distance_min%type;
  distance_max               redemption_billing_mpr.distance_max%type;

  after each row is
  begin
    id                         := :new.id;
    redemption_billing_company := :new.redemption_billing_company;
    distance_min               := :new.distance_min;
    distance_max               := :new.distance_max;
  end after each row;

  after statement is
  begin
    v_is_distance_range_valid := p_redemption_billing.is_distance_range_valid(id,
                                                                              redemption_billing_company,
                                                                              distance_min,
                                                                              distance_max,
                                                                              'redemption_billing_mpr');
    if not v_is_distance_range_valid then
      raise_application_error(-20001, 'This is a custom error');
    end if;
  end after statement;

end ab_redemption_billing_mpr;

我们必须使用复合触发器来处理它。


0
投票

首先,我要感谢psaraj12的努力。

我找到了解决方案。 Oracle强迫我们不要在每一行之前使用选择查询。Oracle trigger error ORA-04091

© www.soinside.com 2019 - 2024. All rights reserved.