【问题标题】:PL SQL: missing row inserted in an TRIGGER with AFTER INSERTPL SQL:使用 AFTER INSERT 插入 TRIGGER 中的缺失行
【发布时间】:2014-09-20 22:20:23
【问题描述】:

我将尝试解释与触发器功能相关的问题。我想在表格中添加一行,将注意力集中在列中的特定数字上,称为“投票”(VOTE),例如:

ID  UTENTE_ID  DATA       COMMENTO     ISBN            VOTO
50  423573     29-LUG-14  CAPOLAVORO!  9788804508359   5

插入后会触发这样的触发器:

create or replace TRIGGER CREATE_COMMENT
AFTER INSERT OR UPDATE ON RECENSIONI
FOR EACH ROW

pragma autonomous_transaction;

BEGIN
    UPDATE LIBRI
    SET VOTOPROD_MEDIA=(SELECT AVG(VOTO) FROM RECENSIONI WHERE ISBN=:NEW.ISBN GROUP BY ISBN)
    WHERE ISBN=:NEW.ISBN;

END;

这里解释了这个触发器背后的想法:我必须添加一个带有 VOTE 的行,然后,它将在另一个名为 LIBRI(书籍)的表中选择一行,并带有一个名为 VOTOPROD_MEDIA(书籍的平均速率)的参数将存储与该书相关的 cmets 的所有投票的平均比率 (AVG)。

触发前的示例:

表格评论:

ID  USER_ID  DATE       COMMENT     ISBN            VOTE
50  423573   29-LUG-14  CAPOLAVORO! 9788804508359   5

表书:

ISBN           AVERAGE_VOTE
9788804508359  5

触发后我会做什么的示例:

表格评论:

ID  USER_ID  DATE       COMMENT     ISBN            VOTE
50  423573   29-LUG-14  CAPOLAVORO! 9788804508359   5
51  423574   29-LUG-14  BAD BOOK!   9788804508359   1

表书:

ISBN           AVERAGE_VOTE
9788804508359  3

3 是 5 和 1 的“AVG”值。

不幸的是,它不起作用。最后一次插入似乎不会影响该更新。事实上,虽然这个触发器表 COMMENTS 的执行,我想,还没有更新插入的新行,所以,当它尝试制作 AVG 时,Table Books 中的 VOTE 保持为 5,而不是更改为 3 .

即使我使用“AFTER INSERT”,但我认为在触发期间,表“RECENSIONI”仍处于此状态:

ID  USER_ID  DATE       COMMENT     ISBN            VOTE
50  423573   29-LUG-14  CAPOLAVORO! 9788804508359   5

我几乎可以肯定,因为同样的“问题”发生在另一个触发器中。好吧,我希望以一种自动的方式“避免”这个结构性问题,创建一种“方式”来在插入或更新之后进行此计算,但真正插入该行。

我该怎么做?

【问题讨论】:

  • 您正在使用自治事务来避免变异表问题;但这意味着触发器无法看到表中未提交的数据(您正在插入)。无论如何,尝试使用触发器保持此值将序列化插入,但充其量。您是否考虑过一个动态计算平均值的视图?如果效果不够好,甚至是物化视图?
  • 这就是问题所在......我如何在不改变表问题的情况下执行触发器?我会尝试使用视图,谢谢:)
  • 但老实说,我不知道如何使用以这种方式生成的列创建视图...

标签: sql oracle plsql triggers


【解决方案1】:

首先,您在触发器中缺少COMMIT 之前的END;。其次,您想使用AUTONOMOUS_TRANSACTION PRAGMA,但我认为这不是一个好的解决方案:如果您要回滚主事务中的更改,触发器内的更新将被提交。此外,如果您只计算音符的平均值,那么分组并不是真正必要的。

【讨论】:

  • 原始触发器要长得多,我忘了粘贴 COMMIT。我不得不使用自治事务,而不是它给了我错误。
【解决方案2】:

您可以使用以下内容创建一个简单的视图:

CREATE OR REPLACE VIEW V_LIBRI AS
SELECT L.ISBN, AVG(R.VOTO) AS VOTO_MEDIO
FROM LIBRI L
LEFT JOIN RECENSIONI R
ON R.ISBN = L.ISBN
GROUP BY L.ISBN;

SQL Fiddle 演示。不需要触发器。对于视图性能不佳的大量数据,您可以考虑使用物化视图,但这有利有弊(例如需要更多存储空间)。

【讨论】:

  • 它就像一个魅力。我还没有很好地使用左右连接,我必须进一步了解它们。非常感谢! :D
  • 这应该是这里的答案,触发器闻起来像是一个糟糕的选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 2023-03-24
  • 2020-12-23
  • 2014-11-24
相关资源
最近更新 更多