首页 > 解决方案 > 触发选择子记录,乘以它们的值并更新父记录

问题描述

我是一个 PL/SQL 新手,我正在为触发器而苦苦挣扎。

描述:

我有三个对象 - 产品、包含、订单。一个产品可以有多个 CONTAINS,一个 ORDER 可以有多个 CONTAINS(基本上它曾经是 PRODUCT 和 ORDER 之间的多对多关系)。

每个产品都有一个“值”列,每个包含有一个“金额”列,每个订单都有一个“总计”列。

当我通过创建新的 CONTAINS 将新产品添加到 ORDER 时,我想重新计算 ORDER 上的字段“总计”。

示例:产品 X 的“值”为 100。产品 Y 的“值”为 200。我们有一个 ORDER O。现在我在产品 X 和 ORDER O 之间创建 CONTAINS,列“数量”为 5。现在触发器应该乘以 5 * 100 并将 ORDER 列“total”更新为 500。然后我在 PRODUCT Y 和 ORDER O 之间创建 CONTAINS,列“amount”为 10。现在触发器应该重新计算 5 * 100 + 10 * 200 并更新“total”列订购 O 至 2500。

我的错误触发器:

    create or replace TRIGGER TRIGGER1 
AFTER DELETE OR INSERT OR UPDATE OF AMOUNT, PRODUCT_ID_PRODUCT, ORDER_ID_ORDER ON CONTAINS 
REFERENCING NEW AS n
FOR EACH ROW
DECLARE
value number;
amount number;
total number;
BEGIN
LOOP
FOR emp IN (SELECT AMOUNT, PRODUCT_ID_PRODUCT, ORDER_ID_ORDER FROM CONTAINS WHERE ORDER_ID_ORDER = :n.ORDER_ID_ORDER) 
LOOP
(SELECT SUM(VALUE) into product FROM PRODUCT WHERE ID_PRODUCT = :emp.PRODUCT_ID_PRODUCT);
amount:= emp.AMOUNT;
total:= total + (product * amount);
UPDATE ORDER SET ORDER.TOTAL = total WHERE ID_ORDER = :n.ORDER_ID_ORDER;
END LOOP;
END LOOP;
END;

编辑:错误显示在这里:

(SELECT SUM(VALUE) into product FROM PRODUCT WHERE ID_PRODUCT = :emp.PRODUCT_ID_PRODUCT)

说我不能使用“emp”。

EDIT2:错误消息:

10/2 PLS-00103:在预期以下情况之一时遇到符号“SELECT”:(-+ case mod new not null continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date pipe <an交替 10/89 PLS-00103:在预期以下情况之一时遇到符号“)”:。( * @ % & - + ; / at for mod remaining rem <an exponent (**)> and or group have intersect minus order start union where connect || indicator multiset 15/5 PLS-00103:遇到符号“LOOP”预期以下情况之一时:

标签: databaseoracleplsqltriggersmutating-table

解决方案


你有几个问题,但最基本的一个是你根本不应该这样做。试图存储 - 并保持同步 - 一个始终可以计算的值是一个基本的设计缺陷。

现在,到代码本身。你有

SELECT SUM(VALUE) into product

INTO 的目标必须是声明的变量。看起来您正在尝试 SELECT .. INTO 列名。

您应该命名局部变量以区分它们的列名。因此,而不是

DECLARE
value number;
amount number;
total number;

你应该有

DECLARE
v_value number;
v_amount number;
v_total number;

相反,您应该考虑表和列的标准命名约定。对于列,我使用并推荐 <adjective_noun> 形式的名称,例如 ORDER_ID、PRODUCT_NAME 等。 PRODUCT_ID_PRODUCT、ORDER_ID_ORDER 是什么?在列名中重复表名通常没有好处。尽管有时它是有意义的,因为它仍然遵循 adjective_noun 格式,例如 ORDERS 表的 id 列被命名为 ORDER_ID。还要考虑表名,我通常将表名设为复数名词,因为表跟踪某个实体的多个实例。如果表名对列名(如 ORDER_ID)有意义,那么它将是单数的,因为单个行跟踪实体的单个实例。

最后,在不了解表格的情况下很难推荐编码修改。您已经对它们进行了模糊的描述,但最好将所有内容都放在桌面上。请参阅最小可重现示例


推荐阅读