数据库设计:基于另一个表的一个表的状态

时间:2013-09-24 15:10:40

标签: database oracle database-design stored-procedures triggers

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

两个表都有一个“状态”列,但这是一个棘手的地方。我的要求是增强的状态取决于其相关的错误。例如,如果我们有3个Bug,其EnhancementID为100,状态为“In Testing”,则Enhancement 100的状态应自动设置为“In Testing”。有这样的状态规则。

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

所以我的问题是:我是否合理地解决了这个问题?有人建议有更好的方法吗?也许使用增强功能的视图?

3 个答案:

答案 0 :(得分:5)

使用视图。

没有简单的方法来跨行/表同步数据。正如您所发现的那样,触发器会导致变异错误,并且是不可数错误的来源。如果你想避免改变错误,请看看workaround by 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调用此函数。

该视图还具有以下优点:当规则发生变化时(与大多数规则一样),您无需更新整个表格。

答案 1 :(得分:0)

this类似的东西可能有用。

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

答案 2 :(得分:0)

我看到了两个解决方案。

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