2010-06-13 54 views
2

我有一个关于那个我设计并确保它是一个标准化的数据库中快速的问题...简单的数据库正常化问题

我有一个客户表,与客户ID的主键。它有一个StatusCode列,其中有一个反映客户帐户状态的代码,即。 1 =打开,2 =关闭,3 =暂停等...

现在我想在客户表中有另一个字段标记帐户是否被允许暂停或不...某些客户将如果他们打破那里的交易条款......别人不会自动挂起......所以相关表中的字段会像这样:

客户(客户编号(PK):的StatusCode:IsSuspensionAllowed)

现在,这两个领域都依赖因为您无法确定特定客户的状态或是否允许暂停,除非您知道特定客户,当然,当IsSuspensionAllowed字段设置为YES时,客户永远不应该有StatusCode为3(暂停)。

从上表设计看来,除非检查限制添加到我的表中,否则可能发生这种情况。我看不出如何将另一个表添加到关系设计中来强制执行此操作,因为只有在IsSuspensionAllowed设置为YES且StatusCode设置为3(两者相互依赖时)的情况下。

因此,在我漫长的解释后,我的问题是:这是一个规范化问题,我没有看到一个关系设计,将强制执行此操作......或者它实际上只是一个业务规则,应该强制执行检查约束并且表格实际上仍然正常化。

干杯,

史蒂夫

回答

0

是的,它是可能的。您可以使用检查约束和Case语句执行此操作:

Create Table Customer (
     CustomerId <datatype> not null Primary Key 
     , StatusCode int not null 
     , IsSuspensionAllowed int not null Default(1) 
     , Constraint CK_Customer_IsSuspensionAllowed 
        Check (IsSuspensionAllowed In(0,1)) 
     , Constraint CK_Customer_StatusCodeRange 
        Check (StatusCode Between 0 And ??) 
     , Constraint CK_Customer_StausCodeValid 
        Check (Case 
       When StatusCode = 3 And IsSuspensionAllowed = 1 Then 0 
                   Else 1 
                   End = 1) 
     , .... 
     ) 

您没有提到PK的数据类型,因此我只是插入了占位符。如果您使用的是SQL Server,那么可以使用一个位列来代替int和我上面提到的检查约束(bit不是ANSI规范的一部分)。

这是一个很好的例子,例如状态代码的替代键并不总能很好地工作。字符串值代表状态码会更好,在这种情况下,Case语句将显示为When StatusCode = 'Suspended' And IsSuspendedAllowed = 0...

从规范化的角度来看,我没有看到任何错误。是否允许暂停是特定于客户的属性,而不是其他属性。你说的检查约束,属性值的某些状态不能存在,这很好。

顺便说一句,当IsSuspensionAllowed = 0时不允许说“Suspended”的状态是不允许的?使用你的数据,不应该是不允许的状态是StatusCode = 3 and IsSuspensionAllowed = 0

+0

谢谢, 我正在规范化和“完整的钥匙,但没有什么,但关键”的事情正在给一些怀疑。我觉得Status和IsSuspended之间可能存在传递依赖关系。正如你所提到的,尽管每个属性都是特定于客户的。 我承认我喜欢在大多数情况下使用代理键进行标准化。我通常只会遇到已经开发的标准,比如货币,或者代表多对多关系的表格。我对你的评论是关于如何提高板载可读性,并且会认为它是不变的代码。 干杯 – Steven 2010-06-13 05:52:17