2010-03-01 58 views
0

我有一个模型,它看起来是这样的:在建模标题/细节关系时消除冗余关系?

Model

一个帐户拥有众多分支机构,并为一个账户中产生的每条语句。该模型是多余的,因为帐户(标题上的AccountID)可以从事务的BranchID中推断出来(一个语句总是会有一个或多个事务)。

应该从StatementHeader中删除AccountID,还是这种冗余级别好?还是有更好的解决方案?

+0

我会避免使用“ID”作为每个表中主键的名称;你最终会在你的模型中加载它们,并且永远无法确定你所指的是哪一个。 如果您使用代理键,那么我建议您在整个模型中使用相同的名称。您已将AccountID作为外键,因此对主键使用相同的名称。 – Tony 2010-03-01 13:14:33

+0

命名约定由其他人设定,所以我不能真正改变它。我赞赏你的理由,但我也有同样的担忧。 – ilitirit 2010-03-01 14:15:43

+0

什么是StatementHeader的实体?在现实世界中,具有相同的StatementHeaderID的语句是相互连接的,还是AccountID和StatementDate都是共享的?后者会使StatementHeader类似于带有SatementHeaderID的日历作为伪装日期... – wallenborn 2010-03-03 13:30:06

回答

0

如果你有StatementHeader,那么它应该有AccountID来保持参照完整性。

但是,最好将StatementHeader完全移除并将StatementDate移动到Statement记录中。这会使事情变得更清洁,并使模型更好地描述你想要的东西。

+0

虽然这只是将冗余移动到记录,因为每条记录都具有相同的声明日期。 – ilitirit 2010-03-01 12:30:07

+0

它使每个声明记录自成一体,这是很好的。 并非所有冗余都不好 - 在这种情况下,性能会更好,因为您可以消除连接以获取日期。 我明白,在声明日期可能发生变化的情况下,有一个'StatementHeader'表允许操纵日期,但除非我是错误的声明日期在这种情况下不会经常改变,所以它是可以接受的。 – 2010-03-01 13:09:24

0

作为一个陈述是历史性的,通常只读,数据一些redundency是好的。我同意Richard Harrison的意见,并将[AccountID]和[StatementDate]都移至[Statement]表中;我的理由是你说一个账户有很多分支机构,所以你将为一个账户生成一个声明。

将所有这些数据存储在同一个地方将减少连接和加快报告,我认为这是数据库的原因。

0

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

要强制执行该规则,您可以尝试创建一个数据库模式,使其无法违反它,或者使用约束或触发器显式强制执行。而且这似乎更容易与StatementHeader.AccountID。在Oracle中,你可以写这样的事情:在StatementHeader

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; 

没有帐户ID,你必须写与共享同一StatementID所有其他语句中的所有其他AccountIDs进行比较,从而产生更复杂报表序列。

所以我会将AccountID作为一个外键在StatementHeader中,并用触发器明确地强制执行业务规则。