此处不允许列
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) 您从PRODUCT
和ORDERLINE
中选择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
、vend_qty
和 shipping_method
在插入到PRODVENDOR
中来自哪里?这是唯一跳出来的明显编译错误。
e) 您没有在插入中指定表格列。如果您的值顺序错误或缺少任何值,这将导致编译错误,但您不能仅通过查看代码来判断。 (在@WW 的更改之后,您还没有说'so may' 错误是什么,所以不知道这是否相关)。并且如果稍后添加另一列,此触发器将变为无效,因此明确列出列通常是个好主意。
从功能上讲,您似乎是在发送一封电子邮件,说整个订单都处于延期交货状态,而不仅仅是这个产品;并且当前订单与您提交给BACKORDER
和PRODVENDOR
的内容之间似乎没有任何联系。
【讨论】:
这可能比预期的更严厉。也许我今天早上的心情比我意识到的要糟糕......【参考方案3】:您确定 QOH 是 ORDERLINE 表中的一个字段吗?老人。和:新。关键字仅适用于安装触发器的表。
【讨论】:
以上是关于此处不允许列的主要内容,如果未能解决你的问题,请参考以下文章
Apache 服务器上的 500 错误 - “此处不允许允许覆盖”