инициализация составной триггерной переменной - PullRequest
0 голосов
/ 29 октября 2019

У меня есть триггер, который выглядит так:

create or replace trigger xxlm_rms_mdm123_aid
  for insert or delete on uda_item_lov
  compound trigger

  type xxlm_rms_mdm123_aid_rec is record(
    item      item_master.item%TYPE,
    uda_value uda_item_lov.uda_value%TYPE);

  type xxlm_rms_mdm123_aid_tbl is table of xxlm_rms_mdm123_aid_rec index by pls_integer;

  L_ctgpro_flag      number;
  L_data_tbl         xxlm_rms_mdm123_aid_tbl;
  L_data_tbl_idx     number;
  L_item             item_master.item%TYPE;
  L_wldpro_uda_id    code_detail.code_desc%TYPE;
  L_ctgpro_uda_id    code_detail.code_desc%TYPE;
  L_wldpro_uda_value uda_item_lov.uda_value%TYPE;

  before statement is
  begin
    L_data_tbl.delete;
    L_data_tbl_idx := 0;
  end before statement;

  before each row is
  begin
    select sign(count(1))
      into L_ctgpro_flag
      from code_detail cd
     where cd.code_type = 'X123'
       and cd.code = 'CTGPRO'
       and cd.code_desc = coalesce(:new.uda_id, :old.uda_id);

    if L_ctgpro_flag = 1 then
      L_data_tbl_idx := L_data_tbl_idx + 1;
      L_data_tbl(L_data_tbl_idx).item := coalesce(:old.item, :new.item);
      L_data_tbl(L_data_tbl_idx).uda_value := coalesce(:old.uda_value,
                                                       :new.uda_value);
    end if;
  end before each row;

  after statement is
  begin
    if L_data_tbl.count > 0 then         
      select max(code_desc)
        into L_wldpro_uda_id
        from code_detail
       where code_type = 'X123'
         and code = 'WLDPRO';

      select max(code_desc)
        into L_ctgpro_uda_id
        from code_detail
       where code_type = 'X123'
         and code = 'CTGPRO';

      if L_wldpro_uda_id is not null then
        for idx in 1 .. L_data_tbl.count loop
          L_item := L_data_tbl(idx).item;

          select max(substr(uv.uda_value_desc, 1, 2))
            into L_wldpro_uda_value
            from uda_values uv
           where uv.uda_id = L_ctgpro_uda_id
             and uv.uda_value = L_data_tbl(idx).uda_value;

          if L_wldpro_uda_value is not null then
            if inserting then
              insert into uda_item_lov
                (item,
                 uda_id,
                 uda_value,
                 create_datetime,
                 last_update_datetime,
                 last_update_id)
              values
                (L_item,
                 L_wldpro_uda_id,
                 L_wldpro_uda_value,
                 sysdate,
                 sysdate,
                 user);
            elsif deleting then
              delete uda_item_lov
               where item = L_item
                 and uda_id = L_wldpro_uda_id
                 and uda_value = L_wldpro_uda_value;
            end if;
          end if;
        end loop;
      end if;
    end if;
  end after statement;
end;

Это дает числовую ошибку, которая говорит о том, что L_data_tbl_idx является нулевым. И для меня это выглядит странно, потому что это должно быть инициализировано с оператором before. Если во время объявления я инициализирую переменную, вот так:

L_data_tbl         xxlm_rms_mdm123_aid_tbl;
L_data_tbl_idx     number := 0;  -- <-- here it is
L_item             item_master.item%TYPE;

Работает нормально. Может кто-нибудь сказать мне, что здесь происходит и почему переменная не инициализируется в первом случае? Спасибо!

Ответы [ 3 ]

2 голосов
/ 29 октября 2019

Проверьте документацию о составном триггере:

"Необязательная декларативная часть составного триггера объявляет переменные и подпрограммы, которые могут использоваться всеми его разделами точки синхронизациииспользовать. Когда триггер срабатывает, декларативная часть запускается перед выполнением любых секций временной точки. Переменные и подпрограммы существуют на время действия запускающего оператора. "

Так что в вашем случае этоошибки, потому что вы инициализируете l_data_tbl_idx в разделе с указанием времени, а не в декларативной части. Инициализация в разделе before statement существует только в области действия этого временного отрезка.

0 голосов
/ 30 октября 2019

Я хочу сказать, что до утверждения работает как задумано. В конце обнаружена проблема, и она была связана не с триггером, а с кодом, который вставляет записи.

0 голосов
/ 29 октября 2019

Я бы предложил так:

CREATE OR REPLACE TRIGGER xxlm_rms_mdm123_aid
  FOR INSERT OR DELETE ON uda_item_lov
  COMPOUND TRIGGER

  TYPE xxlm_rms_mdm123_aid_rec IS record(
    item      item_master.item%TYPE,
    uda_value uda_item_lov.uda_value%TYPE);

  TYPE xxlm_rms_mdm123_aid_tbl IS TABLE OF xxlm_rms_mdm123_aid_rec; -- without INDEX BY PLS_INTEGER

  L_data_tbl         xxlm_rms_mdm123_aid_tbl;

  BEFORE STATEMENT IS
  BEGIN
    L_data_tbl := xxlm_rms_mdm123_aid_tbl();
  END BEFORE STATEMENT;


  BEFORE EACH ROW IS
  BEGIN
      ...
    L_data_tbl.extend;
    L_data_tbl(L_data_tbl.last).item := COALESCE(:old.item, :new.item);
    L_data_tbl(L_data_tbl.last).uda_value := COALESCE(:old.uda_value, :new.uda_value);

  END BEFORE EACH ROW;

Тогда вам не нужно поддерживать индекс L_data_tbl_idx.

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