Триггер для расчета промежуточных итогов - PullRequest
0 голосов
/ 08 декабря 2011

Я уже некоторое время пытаюсь реализовать этот триггер и делаю успехи (я думаю!), Но сейчас я получаю ошибку мутации.

Здесь у меня есть три объекта (которые здесь актуальны), Customer_Order (итого и т. Д.), Order_Line (количество, промежуточный итог и т. Д.) И Products (запас, цена).Order_line является ссылочной сущностью, и поэтому товар может быть представлен во многих order_lines, а customer_order может иметь много order_lines, но order_line может появляться только один раз в заказе и может содержать только один продукт.Цель триггера - взять промежуточную сумму из order_line (или цены из продуктов, которые я считаю на самом деле) и количество из order_line, умножить их и обновить промежуточный итог новой order_line.

Поэтому я вставляю order_line с моим продуктомВо внешнем ключе, количестве 3 и цене 4,00, триггер умножает их на 12 и обновляет промежуточный итог.Теперь я думаю, что здесь правильно использовать цену вместо подытога Order_line, чтобы исправить ошибку мутации (которая возникает из-за того, что я прошу триггер обновить таблицу, к которой обращается оператор триггера, верно?), Но какисправить проблему с количеством?Количество не всегда будет таким же, как запас, оно должно быть меньше или равно запасу, поэтому кто-нибудь знает, как я могу это исправить, чтобы выбрать из продукта и обновить order_line?Спасибо.

CREATE OR REPLACE TRIGGER create_subtotal  
BEFORE INSERT OR UPDATE ON Order_Line 
for each row
DECLARE 
currentSubTotal order_line.subtotal%type;
currentQuantity order_line.quantity%type;
BEGIN 
select order_line.subtotal,order_line.quantity
into currentSubTotal,currentQuantity
from order_line
where product_no = :new.product_no;
IF (currentquantity>-1 ) then 

update order_line set subtotal= currentSubTotal * currentQuantity where     line_no=:new.line_no;

END IF;
END; 
. 
run

РЕДАКТИРОВАТЬ: Я думаю, что я мог бы использовать синтаксис: новый, чтобы использовать значение количества из оператора запуска.Я попробую это, но я буду благодарен за подтверждение и помощь, спасибо.

Ответы [ 2 ]

1 голос
/ 08 декабря 2011

Звучит так, как будто вы хотите что-то вроде

CREATE OR REPLACE TRIGGER create_subtotal
  BEFORE INSERT OR UPDATE ON order_line
  FOR EACH ROW
DECLARE
  l_price products.price%type;
BEGIN
  SELECT price
    INTO l_price
    FROM products
   WHERE product_no = :new.product_no;

  IF( :new.quantity > -1 )
  THEN
    :new.subtotal := :new.quantity * l_price;
  END IF;
END;

Однако, если это не домашняя работа, не имеет смысла вытягивать цену из таблицы PRODUCTS в этом триггере. Предположительно, цена товара со временем изменится. Но цена фиксируется для конкретного заказа, когда заказ размещен. Если триггер был определен только на INSERT, вероятно, было бы разумно просто получить текущую цену. Но если вы хотите пересчитать промежуточный итог строки при обновлении строки, вам нужно будет получить цену на момент размещения заказа (и это предполагает, что вы не взимаете с разных клиентов разные цены по одной цене). время).

С точки зрения нормализации также не имеет смысла сохранять вычисленные поля в первую очередь. Было бы разумнее сохранить количество и цену в таблице order_line, а затем вычислить промежуточный итог для строки в представлении (или, если вы используете 11g, в качестве виртуального столбца в таблице).

1 голос
/ 08 декабря 2011

Ошибка мутации не происходит, потому что вы обновляете таблицу; это происходит потому, что вы запрашиваете из таблицы, которая уже обновляется.

Если я правильно понимаю, что вы хотите сделать:

CREATE OR REPLACE TRIGGER create_subtotal  
BEFORE INSERT OR UPDATE ON Order_Line 
for each row
DECLARE 
  currentPrice  products.price%TYPE;
BEGIN
  -- Get the current price for the product
  SELECT price INTO currentPrice FROM products WHERE product_no = :new.product_no;

  -- Set the new subtotal to the current price multiplied by the order quantity
  :new.subtotal := currentPrice * :new.quantity;
END;
/

(Мне неясно, почему у вас есть тест для количества ниже 0, и что вы хотите получить в этом случае. Если вы хотите установить промежуточный итог в NULL или 0 в этом случае, это должно быть довольно легко изменить выше.)

...