0

我有一个奇怪的业务需求,让我很难过。一些背景知识:基本上,我有两个用于跟踪程序改进的表:Enhancement 和 Bug。Enhancement->Bug的关系是1:m,Bug表有一个外键列EnhancementID。

两个表都有一个“状态”列,但这就是它变得棘手的地方。我的要求是增强的状态取决于其相关的错误。例如,如果我们有 3 个错误,增强 ID 为 100,状态为“测试中”,则增强 100 的状态应自动设置为“测试中”。有几个像这样的状态规则。

这个数据库由几个应用程序共享,所以我的第一个想法是在 Bug 表上使用“更新时”触发器。因为触发器在触发表中有一条 Select 语句,所以我收到“变异表”错误(当触发器触发时,我必须查询具有指定 EnhancementID 的所有错误的状态)。现在,我正在尝试实现此处概述的三个触发器解决方案:http ://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936但我对在数据库触发器中放置如此​​多的逻辑变得谨慎。

所以我的问题是:我是否合理地解决了这个问题?有人可以提出更好的方法吗?也许使用增强状态的视图?

4

3 回答 3

5

使用视图。

没有简单的方法可以跨行/表同步数据。正如您发现的那样,触发器会导致变异错误并且是无数错误的来源。如果您想避免变异错误,请查看Tom Kyte 的这个解决方法(这可能会帮助您理解为什么触发器在这种情况下不是最好的工具)。

您可以使用应用程序过程或 PL/SQL API,但请注意,它们只有在您一直使用它们时才能工作(这意味着您永远不会对这些表进行一次直接更新)。忘记使用 API 的单个开发人员将使您的数据不同步。就我个人而言,如果状态是如此复杂以至于无法即时计算,以至于视图在性能方面不可接受,我只会考虑使用 API。

由于这是冗余信息(增强的状态可以完全从其错误状态中扣除),您不需要将其存储在数据库列中。

如果您可以在 SQL 查询中表达您的规则,这很简单,例如:

CREATE OR REPLACE VIEW enhancement_with_status_v AS
SELECT e.*,
       CASE WHEN COUNT(DECODE(b.status, 'T', 1)) >= 1 THEN 'T'
            WHEN ...
            ELSE ...
       END status
  FROM enhancement e,
  LEFT JOIN bugs b ON b.enhancement_id = e.enhancement_id
 GROUP BY e...

如果规则太复杂,您可以编写一个 PL/SQL 函数并从 SQL 调用该函数。

该视图还有一个优点,即当规则发生变化时(正如大多数规则所做的那样),您无需更新整个表。

于 2013-09-24T15:25:30.180 回答
0

与此类似的东西可能会起作用。

尝试在更新后触发一个来检查每个增强的不同状态并在增强中更新相同的状态。

于 2013-09-24T15:18:53.890 回答
0

我看到了两种解决方案。

  1. 问题中提到的数据库触发器
  2. 使用您的应用程序手动更新父状态(增强状态)。不要忘记在子表中索引外键,否则在分布式应用系统中死锁是不可避免的
于 2013-09-24T15:21:02.373 回答