代码之家  ›  专栏  ›  技术社区  ›  ilitirit

在建模头/细节关系时消除冗余关系?

  •  0
  • ilitirit  · 技术社区  · 16 年前

    我有一个这样的模型:

    Model

    一个帐户有多个分支,每个报表都是为一个帐户生成的。该模型是多余的,因为可以从事务的branchhid推断出帐户(头上的accountid)(语句将始终有一个或多个事务)。

    应该从StatementHeader中删除AccountID,还是可以使用此级别的冗余?还是有更好的解决方案?

    3 回复  |  直到 16 年前
        1
  •  0
  •   Richard Harrison    16 年前

    如果您有statementHeader,那么它应该有AccountID来保持引用的完整性。

    不过,最好完全删除statementHeader并将statementDate移到语句记录中。这将使事情更清楚,使模型更好地描述您想要的。

        2
  •  0
  •   Tony    16 年前

    由于语句是历史性的,而且通常是只读的,所以某些冗余数据是可以的。我同意Richard Harrison的观点,我会把[AccountID]和[StatementDate]都移到[Statement]表中;我的理由是你说一个账户有很多分支,所以你将为一个账户生成一个报表。

    将所有这些数据存储在同一个位置将减少连接并加快报告速度,我认为这是该数据库的原因。

        3
  •  0
  •   wallenborn    16 年前

    有时,(真实的或感知的)冗余是业务规则的结果。在这种情况下,业务规则是:“向账户发出的报表应仅包含属于该特定账户的分行的交易。”

    要强制执行该规则,可以尝试创建一个数据库架构,使其不可能违反该规则,或者使用约束或触发器显式强制执行该规则。使用statementHeader.accountID似乎更容易。在Oracle中,您可以这样写:

    create or replace trigger statement_has_unique_account
    before insert or update on Statement
    referencing old as old new as new
    for each row
    declare
      m integer;
      n integer;
    begin
      select b.AccountID
      into m
      from Branch b 
      where b.ID = new.BranchID;
    
      select s.AccountID
      into n
      from StatementHeader s
      where s.ID = new.StatementID;
    
      if m <> n then
        raise_application_error(-1000, 'No way!');
      end if;
    end;
    

    如果statementHeader中没有accountID,则必须与共享同一statementID的所有其他语句中的所有其他accountID进行比较,从而生成更复杂的语句序列。

    因此,我将accountid作为外键保留在statementHeader中,并使用触发器显式地强制执行业务规则。

    推荐文章