Oracle Триггер для проверки значений при вставке и обновлении - PullRequest
1 голос
/ 12 апреля 2020

Я пытаюсь проверить разницу между ценностями или нет. Позвольте мне объяснить с коротким сценарием.

Re c 1: Компания AA: Разрыв расстояния -> 100 - 200
Re c 2: Компания AA: Разрыв расстояния -> 200 - 300 ДЕЙСТВИТЕЛЬНО
Re c 3: Компания AA: Разрыв расстояния -> 250 - 450 Недействительно
Re c 4: Компания JL: Разрыв расстояния -> 250 - 450 VALID

Re c 3 Неправильно, потому что оно находится между значениями расстояния RE C 2. Re c 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: имя таблицы меняется, триггер / функция может его не видеть

и оно указывает select count(*) строку, когда я нажимаю кнопку отладки.

Я не знаю, почему я Я получаю эту ошибку. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

Просто проверьте, разрешает ли ваша проблема приведенный ниже подход

Создайте таблицу журнала со столбцами, необходимыми для поиска проверки is_distance_range_valid, и вставьте в свой триггер эту вкладку журнала. Триггером на главной таблице должен быть перед триггером вставки или обновления

Создайте триггер для этой таблицы журнала и выполните проверку в триггере таблицы журнала и вызовите ошибку. Триггер в таблице журнала должен быть после вставки или триггер обновления .

Также это будет работать, только если строка уже существует в основной таблице и не является частью текущей вставки или обновления. Если требуется проверка текущей вставки или обновления, тогда нам нужно использовать: new.column_name для проверки

Test: -

    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;

При первой вставке это не происходит t throw error

  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

0 голосов
/ 13 апреля 2020

Сначала я хочу поблагодарить psaraj12 за его усилия.

Я нашел решение. Oracle заставляет нас не использовать запрос выбора перед каждой строкой. Oracle ошибка триггера 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;

Мы должны использовать сложный триггер, чтобы справиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...