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

Database 数据库设计:一个表基于另一个表的状态,database,oracle,database-design,stored-procedures,triggers,Database,Oracle,Database Design,Stored Procedures,Triggers,我有一个奇怪的业务需求,这让我感到困惑。一些背景:基本上,我有两个跟踪程序增强的表:增强和Bug。Enhancement->Bug的关系是1:m,Bug表有一个外键列EnhancementID 这两个表都有一个“Status”列,但这正是它变得棘手的地方。我的要求是,增强的状态取决于其相关的bug。例如,如果我们有3个Bug,EnhancementID为100,状态为“测试中”,那么Enhancement 100的状态应该自动设置为“测试中”。有几个类似的状态规则 这个数据库由几个应用程序共享,

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

这两个表都有一个“Status”列,但这正是它变得棘手的地方。我的要求是,增强的状态取决于其相关的bug。例如,如果我们有3个Bug,EnhancementID为100,状态为“测试中”,那么Enhancement 100的状态应该自动设置为“测试中”。有几个类似的状态规则

这个数据库由几个应用程序共享,所以我的第一个想法是在Bug表上使用“更新时”触发器。因为触发器在触发表中有一个Select语句,所以我收到一个“mutating table”错误(当触发器触发时,我必须用指定的EnhancementID查询所有bug的状态)。现在,我正试图实现这里概述的三触发器解决方案:但我越来越担心在数据库触发器中放入如此多的逻辑

所以我的问题是:我是否合理地对待这个问题?有没有更好的建议?也许使用视图查看增强功能的状态?

类似的功能可能会起作用

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

类似的操作可能会起作用


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

我看到了两种解决方案

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

  • 我认为有两种解决办法

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

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

    您可以使用应用程序过程或PL/SQLAPI,但请注意,只有始终使用它们,它们才会起作用(这意味着您永远不会对这些表发出任何直接更新)。忘记使用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调用此函数

    该视图还有一个优点,即当规则更改时(与大多数规则一样),您不需要更新整个表。

    使用视图

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

    您可以使用应用程序过程或PL/SQLAPI,但请注意,只有始终使用它们,它们才会起作用(这意味着您永远不会对这些表发出任何直接更新)。忘记使用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时,如果可以,请使用视图。除非您有某种形式的锁定(建议的基于触发器的解决方案没有),否则基于触发器的方法将无法正常工作——根本问题是触发器无法“看到”其他事务所做的更改(例如添加或更新另一个状态为“测试中”的bug)@BrianCamire——为什么触发器不能“看到”其他事务的更改?他们不应该在每次更新Bug状态时都开火吗?我喜欢使用视图的想法,但是