Как решить мутантный триггер - PullRequest
0 голосов
/ 27 июня 2018

Я НОВЫЙ В PL / SQL ORACLE У меня есть проблема, чтобы сделать триггер для стола с мутирующим эффектом

Я ХОЧУ РЕАЛИЗОВАТЬ СЛЕДУЮЩУЮ СЛЕДУЮЩУЮ: ПОСТАВЛЯЯ ЗАКАЗ НА ТАБЛИЦУ ORDER_ITEMS, ЗАКАЗЫВАЕМАЯ СУММА (КОЛИЧЕСТВО) ОБНОВЛЯЕТСЯ В УЧЕТЕ ИНВЕНТАРНЫХ СТОЛОВ (QUANTITY_ON_HAND)

TABLE ORDER_ITEMS
-ORDER_ID
-PRODUCT_ID-
-UNIT_PRICE
-QUANTITY

КЛЮЧ ORDER_ID И ПОВЫШАЕТСЯ ПОСЛЕДОВАТЕЛЬНОСТЬЮ

THE TABLE INVENTORIES
-PRODUCT_ID
-WHAREHOUSE_ID
-QUANTITY_ON_HAND

У меня ВЫПОЛНЕНЫ ФУНКЦИИ, КОТОРЫЕ ПОЛУЧАЮТ ПРОДУКТ_ID И ЗАКАЗАНУЮ КОЛИЧЕСТВО ПОСЛЕДНЕЙ ЗАПИСИ, ВСТАВЛЕННОЙ В ТАБЛИЦУ ORDER_ITEMS

CREATE OR REPLACE FUNCTION get_data__order_quantity
RETURN number IS
quantity_order number;
BEGIN
 select quantity into quantity_order from (select * from ORDER_ITEMS order by order_id desc) where rownum=1;
 RETURN quantity_order ;
END get_data__order_quantity;

CREATE OR REPLACE FUNCTION get_data_cod_prod
RETURN number IS
cod_producto number;
BEGIN
 select product_id into cod_producto from (select * from ORDER_ITEMS order by order_id desc) where rownum=1;
 RETURN cod_producto ;
END get_data_cod_prod;

Я ВЫПОЛНЯЛ ТРИГГЕР ЭТОЙ ФОРМЫ

create or replace trigger actualizar_stock
after insert  --AFTER INSERT
on ORDER_ITEMS  -- ON TABLE ORDER_ITEMS
for each row

declare
 ctn_ordenada int;  --STORE THE AMOUNT OF ORDERED PRODUCTS
 cod_produc int;    --STORE THE ID OF THE PRODUCT THAT HAS BEEN ORDERED
 id_wharehouse int; --STORE THE ID OF THE FIRST WAREHOUSE ENCOUNTERED WITH THE PRODUCT IN EXISTENCE
 stock_bodega int;  --STORE THE EXISTENCE OF PRODUCTS (STOCK) IN BODEGA

begin
  ctn_ordenada:=get_data__order_quantity; --THE AMOUNT ORDERED FROM THE FUNCTION IS ASSIGNED
  cod_produc :=get_data_cod_prod;         -- THE PRODUCT ID IS ASSIGNED FROM THE FUNCTION

  select quantity_on_hand into stock_bodega   from inventories where (quantity_on_hand > 0 and rownum=1 and product_id=cod_produc); -- SE ASIGNA EL STOCK
  select  wharehouse_id into  id_wharehouse  from inventories where (quantity_on_hand > 0 and rownum=1 and product_id=cod_produc);  -- THE ID OF THE WAREHOUSE IS ASSIGNED

 -- IF THE ESTOCK IS GREATER THAN 0
 if (stock_bodega >0) then
 begin
 --UPDATE (REST THE CURRENT VALUE WITH THE ORDERED AMOUNT)
 update inventories set quantity_on_hand=quantity_on_hand-ctn_ordenada where wharehouse_id=id_wharehouse;
 end;
 else
  begin
  -- DO NOT UPDATE
  dbms_output.put_line('Registration not updated');
  end;
  end if;
end;

-- END OF THE TRIGGER

ПОЖАЛУЙСТА, ПОМОГИТЕ

1 Ответ

0 голосов
/ 27 июня 2018

Основная проблема заключается в том, что функции get_data__order_quantity и get_data_cod_prod, которые вызываются из вашего триггера, обращаются к таблице, для которой определен триггер. Это приведет к исключению мутирующей таблицы.

Другая проблема, конечно, в том, что ваши функции, скорее всего, не будут выполнять то, что вы намеревались. Вы говорите: «У меня есть ВЫПОЛНЕННЫЕ ФУНКЦИИ, ПОЛУЧАЮЩИЕ ПРОДУКТА_ID И ЗАКАЗАННОЙ СУММЫ ПОСЛЕДНЕЙ ЗАПИСИ, ВСТАВЛЕННОЙ В ТАБЛИЦУ ORDER_ITEMS», но ваши критерии выбора ...WHERE ROWNUM = 1. Невозможно заранее узнать, какой будет эта запись - при отсутствии конкретных критериев выбора или упорядочения база данных может свободно возвращать строки в любом порядке, в котором она заинтересована. может возвращать последнюю вставленную строку, но может возвращать любую произвольную строку из таблицы. Вы просто не можете знать, основываясь на ROWNUM = 1, что вы вставите последнюю строку в таблицу.

К счастью, вам не нужно ничего этого делать, поскольку у вас уже есть доступ к строке, которая была только что вставлена ​​через псевдоряд :NEW. Я предлагаю переписать ваш триггер как:

create or replace trigger actualizar_stock
  after insert on ORDER_ITEMS
  for each row
begin
  --UPDATE (REST THE CURRENT VALUE WITH THE ORDERED AMOUNT)

  update inventories
    set quantity_on_hand = quantity_on_hand - :NEW.QUANTITY
    where QUANTITY_ON_HAND > 0 AND
          product_id = :NEW.PRODUCT_ID;

  IF SQL%ROWCOUNT = 0 THEN
    -- No rows updated
    dbms_output.put_line('Registration not updated');
  end if;
end actualizar_stock;

Удачи.

...