【问题标题】:Database design: status of one table based on another数据库设计:一张表的状态基于另一张表
【发布时间】:2013-09-29 21:25:38
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    类似于this 的东西可能会起作用。

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

    【讨论】:

    • 我认为这与我在第一次尝试中尝试的类似,我在触发器中使用 SELECT 时收到“变异表”错误。
    • 如果在更新表 a 后尝试更新表 b,为什么会遇到 mutating table 错误?
    • 因为我必须在触发器中查询表 a 以确定表 b 上的状态更新。这会导致变异表错误。
    【解决方案2】:

    我看到了两种解决方案。

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

    【讨论】:

    • 谢谢,但在这里使用应用程序并不是一个真正的选择:数据库在几个应用程序之间共享。
    【解决方案3】:

    使用视图。

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

    该视图还有一个优势,即当规则发生变化时(就像大多数规则一样),您无需更新整个表格。

    【讨论】:

    • 我实际上是根据 Tom Kyte 的解决方法中的建议构建触发器。我遇到的另一个问题是我无法真正更改应用程序以使用与当前增强表不同的表。是否可以根据此视图更新增强表的状态?
    • 所以您正在尝试使用触发器来解决应用程序问题,这一定是......不愉快!您可以重命名您的表并将视图称为“增强”,但这可能会引发更多它解决的问题。确实,如果您无法控制应用程序,那么意外后果将难以预测。
    • 同意@VincentMalgrat - 如果可以,请使用视图。除非您有某种形式的锁定(建议的基于触发器的解决方法没有),否则基于触发器的方法将无法正常工作 - 根本问题是触发器无法“看到”其他事务所做的更改(例如添加或更新另一个状态为“测试中”的错误)。
    • @BrianCamire -- 为什么触发器不能“看到”其他交易的变化?他们不应该在每次更新错误状态时触发吗?我喜欢使用视图的想法,但我正在努力思考这将如何改变事物。从应用程序的角度来看,我不确定将增强表更改为视图的含义是什么。
    • @VincentMalgrat -- 是的,你不知道......我正在尝试使用触发器,因为不同的应用程序会更新 Bug 的状态......所以需要自动更新的状态增强功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多