database - 触发选择子记录,乘以它们的值并更新父记录
问题描述
我是一个 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”预期以下情况之一时:
解决方案
你有几个问题,但最基本的一个是你根本不应该这样做。试图存储 - 并保持同步 - 一个始终可以计算的值是一个基本的设计缺陷。
现在,到代码本身。你有
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)有意义,那么它将是单数的,因为单个行跟踪实体的单个实例。
最后,在不了解表格的情况下很难推荐编码修改。您已经对它们进行了模糊的描述,但最好将所有内容都放在桌面上。请参阅最小可重现示例
推荐阅读
- c# - 结合可观察对象的反应式 UI
- regex - 带有重复字符串的正则表达式负前瞻
- glsl - OpenGL 2D褪色圆被分辨率拉伸/压缩
- java - Java:条件运算符的奇怪行为
- python - 如何使用 Python 从 json 中提取和转换货币值?
- javascript - 在 JavaScript 中序列化复杂对象
- powershell - powershell中的docker cp参数扩展
- outlook-addin - 带有 dovecot 的 Outlook 插件
- deployment - SignTool 错误:发生了意外的内部错误。错误 MSB3482
- python - 通过熊猫df进行python多处理