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

0 database oracle triggers database-design stored-procedures

我有一个奇怪的业务要求,让我难过.一些背景:基本上,我有两个用于跟踪程序增强的表:增强和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但我对在数据库触发器中放置如此​​多的逻辑变得谨慎.

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

Vin*_*rat 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...
Run Code Online (Sandbox Code Playgroud)

如果规则太复杂,您可以编写PL/SQL函数并从SQL调用此函数.

该视图还具有以下优点:当规则发生更改时(与大多数规则一样),您不需要更新整个表.