此处不允许列

Posted

技术标签:

【中文标题】此处不允许列【英文标题】:column not allowed here 【发布时间】:2011-04-12 02:13:48 【问题描述】:
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。如果没有,请向客户发送电子邮件,更新延期交货表,产品应从供应商处订购。

【问题讨论】:

【参考方案1】:

改变这一行:

QOH = :old.QOH - :new.QTY

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

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

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

【讨论】:

谢谢,我尝试更改赋值运算符,但仍然遇到很多错误。【参考方案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_novend_qtyshipping_method 在插入到PRODVENDOR 中来自哪里?这是唯一跳出来的明显编译错误。

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

从功能上讲,您似乎是在发送一封电子邮件,说整个订单都处于延期交货状态,而不仅仅是这个产品;并且当前订单与您提交给BACKORDERPRODVENDOR 的内容之间似乎没有任何联系。

【讨论】:

这可能比预期的更严厉。也许我今天早上的心情比我意识到的要糟糕......【参考方案3】:

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

【讨论】:

以上是关于此处不允许列的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00984: 此处不允许列动态 sql

Apache 服务器上的 500 错误 - “此处不允许允许覆盖”

此处不允许使用 Maven Jetty 插件守护程序元素

Java 8 javadoc doclint 功能“此处不允许标记”

此处不允许使用“set”指令

00984. 00000 - “此处不允许列”