列不允许在这里

时间:2011-04-12 02:13:48

标签: sql oracle function plsql triggers

CREATE OR REPLACE TRIGGER update_QOH
BEFORE INSERT ON ORDERLINE
FOR EACH ROW
DECLARE
    QOH_PRODUCT PRODUCT.QOH%TYPE;
    ORD_NO ORDERS.ORDER_NO%TYPE;
BEGIN
    SELECT QOH INTO QOH_PRODUCT FROM PRODUCT
    WHERE :old.product_no = :new.product_no;

    SELECT ORDER_NO INTO ORD_NO FROM ORDERLINE
    WHERE :old.order_no = :new.order_no;

    IF (:new.QTY <= QOH_PRODUCT) THEN   
        UPDATE PRODUCT SET QOH = QOH_PRODUCT - :new.QTY;
    ELSE
        send_email(ord_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;
/
-------------------------------------------------------------------------------
Error(13,3): PL/SQL: SQL Statement ignored

Error(13,91): PL/SQL: ORA-00984: column not allowed here
--------------------------------------------------------------------------------

产品表(P_no,QOH等)

订单行表(OL_no,QTY等)

延期交货表(B_no,B_QTY等)

供应商表(V_no等)

我需要确保当客户购买产品时,产品表中有足够的QOH,如果有,则应减少(更新)产品中的QOH。如果没有,请向客户发送电子邮件,更新延期交货表,并从供应商处订购产品。

3 个答案:

答案 0 :(得分:2)

更改此行:

QOH = :old.QOH - :new.QTY

QOH := :old.QOH - :new.QTY

在PL / SQL :=中是赋值运算符,因此在设置PL / SQL变量时请使用它。

无论编译错误的来源是什么,从触发器发送电子邮件似乎都是个坏主意。

答案 1 :(得分:2)

首先,考虑将插入放入过程而不是触发器。 (也许是一个更有用的名字)。如果他们稍后获得自己的触发器,那么从这里插入或更新其他表可能会变得混乱,并且很难跟踪在何时何地发生的事情。

其次,这看起来它不能很好地处理并发插入 - 同一产品的两个新的ORDERLINE插入将尝试更新产品QOH可能出现意外或不合需要的结果 - QOH可能会消极, 例如。您也可能会向供应商索取多个订单;请求缺货产品的每个订单行都将向供应商发出新订单,即使每个订单行数量为1,并且您一次从供应商订购100个订单。

第三,各种代码错误;我将从几个更明显的开始:

a)您选择PRODUCTORDERLINE WHERE :old.product_no = :new.product_no。我不确定:OLD是否设置在插入前触发器中,但如果它是:NEW或null,那么你可能会得到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的{​​{1}},vend_qtyshipping_method来自何处?这是跳出来的唯一明显的编译错误。

e)您没有在插入中指定表格列。如果您的值顺序错误或任何丢失,这将导致编译错误,但您无法通过查看代码来判断。 (你还没有说过@WW改变之后'可能'错误是什么,所以不知道这是否相关)。如果稍后添加了另一列,则此触发器将变为无效,因此通常最好明确列出列。

从功能上来说,您似乎正在发送一封电子邮件,说明整个订单都是按订单生产的,而不仅仅是这个产品;并且当前订单与您向PRODVENDORBACKORDER投放的内容之间似乎没有任何关联。

答案 2 :(得分:0)

你确定QOH是ORDERLINE表中的一个字段吗?老人。并且:新的。关键字仅适用于安装触发器的表。