Как исправить ошибку таблицы мутаций в триггере? - PullRequest
0 голосов
/ 29 октября 2018

У меня есть две таблицы с именами item и stock_item. Когда я обновляю таблицу item, должен срабатывать триггер с именем beforeItem, который вычитает новое обновленное значение qty из stock_qty. Но это бросает

ORA-04091: таблица **** является триггерным триггером / функция может его не видеть

Как я могу это исправить?

Мои таблицы:

create table stock_item
(no number primary key,itemName varchar2(10),stock_Qty number);

create table item 
(no number,Name varchar2(10),qty number);   

Мой триггер:

create or replace trigger beforeItem
before update on item
for each row 
declare 
chk_no number;
chk_item varchar2(10);
chk_qty number;
--pragma AUTONOMOUS_TRANSACTION;
-- this code will skip the update code.
begin
select no,name,qty into chk_no, chk_item,chk_qty from item where  no=:new.no 
and name=:new.name;
update stock_item set itemName = itemName - chk_qty where no=chk_no and 
itemName=chk_item; 
--commit;
end; 

Ответы [ 2 ]

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

Вы не можете ссылаться на таблицу ITEM в этом триггере, потому что это вызывает вашу ошибку. Вместо использования оператора SELECT используйте новые / старые параметры. Попробуйте эту версию триггера.

create or replace trigger beforeItem
  before update on item
  for each row 
begin
  -- if :new.qty is not null then
    update stock_item set 
      -- logic to maintaint if no changes on qty field were done
      stock_Qty = stock_Qty - ( nvl(:new.qty,0) - nvl(:old.qty,0) ) 
      where no=:new.no and itemName=:new.name; 
  -- end if;
end;
0 голосов
/ 29 октября 2018

Oracle бросает ORA-04091, когда триггер выдает DML для таблицы, которой принадлежит триггер; это включает в себя инструкции SELECT. Причина проста: состояние таблицы неизвестно, потому что триггер срабатывает во время транзакции , поэтому результат DML триггера непредсказуем.

Решение обычно довольно простое: удалить DML. Это, безусловно, может быть ответом здесь, потому что ваша запись: NEW содержит все значения, необходимые для выполнения обновления на stock_item:

create or replace trigger beforeItem
    before update on item
    for each row 
 begin

    update stock_item si
    set si.stock_Qty = si.stock_Qty - :new.qty 
    where si.no = :new.no; 

end; 

но таблица stock_item не знает, из какого значения вычитается текущее значение таблицы элементов qty.

Хорошо, значит, вы хотите обновить STOCK_ITEM.QTY с разницей между старым (текущим) ITEM.QTY и новым (обновленным) значением. Тогда это будет что-то вроде:

create or replace trigger beforeItem
    before update on item
    for each row 
 begin

    update stock_item si
    set si.stock_Qty = si.stock_Qty - (nvl(:old.qty,0) - nvl(:new.qty,0)) 
    where si.no = :new.no; 

end; 

Вот демонстрация моего решения на SQL Fiddle .


Кстати, обратите внимание, что я исправил ваше утверждение ОБНОВЛЕНИЕ: вычитание количества товара из названия запаса действительно не имеет смысла. Кроме того, нет необходимости использовать itemName в предложении WHERE, где есть первичный ключ для использования.

...