Во-первых, рассмотрите возможность вставки вставки в процедуру вместо триггера. (И, возможно, более полезное имя). Вставка или обновление других таблиц может привести к путанице, если позже они получат свои собственные триггеры, и трудно отслеживать, что и когда происходит.
Во-вторых, похоже, что он не очень хорошо справляется с одновременными вставками - две новые вставки ORDERLINE для одного и того же продукта одновременно будут пытаться обновить QOH продукта с вероятными неожиданными или нежелательными результатами - QOH может стать отрицательным , например. Вы также можете получить несколько заказов поставщику; каждая строка заказа, которая запрашивает товар, отсутствующий на складе, будет делать новый заказ поставщику, даже если количество каждой строки заказа равно 1 и вы заказываете 100 у поставщика за раз.
В-третьих, различные ошибки кода; Я начну с нескольких более очевидных:
a) Вы выбираете из PRODUCT
и ORDERLINE
с WHERE :old.product_no = :new.product_no
. Я не уверен, что :OLD
даже установлен в триггере перед вставкой, но если это так, он будет таким же, как :NEW
или ноль, так что вы, возможно, получите ошибки ORA-02112 или ORA-01403 так как он найдет все строки или, возможно, ни одной.
b) Ваш выбор из ORDERLINE
не вернет ни одной строки в первой строке заказа и нескольких строк начиная с третьей и так далее, так что вы снова получите ошибки ORA-01403 и ORA-02112. Но это бессмысленно, поскольку вы просто выбираете значение, к которому обращаетесь. Вы можете просто использовать значение :NEW
в сообщении электронной почты.
c) В вашем обновлении PRODUCT
нет предложения WHERE
, поэтому все значения QOH будут обновлены.
CREATE OR REPLACE TRIGGER update_QOH
BEFORE INSERT ON ORDERLINE
FOR EACH ROW
DECLARE
QOH_PRODUCT PRODUCT.QOH%TYPE;
BEGIN
SELECT QOH INTO QOH_PRODUCT FROM PRODUCT
WHERE product_no = :new.product_no;
IF (:new.QTY <= QOH_PRODUCT) THEN
UPDATE PRODUCT SET QOH = QOH_PRODUCT - :new.QTY;
WHERE product_no = :new.product_no;
ELSE
send_email(:new.order_no, 'Backorder');
INSERT INTO BACKORDER
VALUES (backorder_no_seq.NEXTVAL, :new.product_no, :new.qty, SYSDATE);
INSERT INTO PRODVENDOR
VALUES (po_no_seq.NEXTVAL, vendor_no, :new.product_no, vend_qty,
shipping_method, SYSDATE, NULL, NULL, NULL);
END IF;
END;
/
d) Откуда vend_no
, vend_qty
и shipping_method
входят во вставку к PRODVENDOR
? Это единственная очевидная ошибка компиляции, которая выскакивает.
e) Вы не указываете столбцы таблицы во вставках. Это приведет к ошибке компиляции, если у вас есть значения в неправильном порядке или отсутствуют, но вы не можете сказать, просто посмотрев код. (Вы не сказали, что это за ошибки «так может» после изменения @ WW, так что не знаете, относится ли это к делу). И если позже добавится еще один столбец, этот триггер станет недействительным, поэтому обычно рекомендуется явно перечислить столбцы.
Функционально вы, похоже, отправляете электронное письмо, в котором говорится, что весь заказ находится на обратном заказе, а не только этот продукт; и, кажется, нет никакой связи между текущим порядком и тем, что вы вводите в BACKORDER
и PRODVENDOR
.