我有一个奇怪的业务要求让我难过。一些背景:基本上,我有两个用于跟踪程序增强的表:增强和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但我对在数据库触发器中放置如此多的逻辑变得很谨慎。
所以我的问题是:我是否合理地解决了这个问题?有人建议有更好的方法吗?也许使用增强功能的视图?
答案 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)
我看到了两个解决方案。