我有一个关于我正在设计的数据库的快速问题,并确保它正常化......
我有一个customer表,主键为customerId。它有一个StatusCode列,其中包含反映客户帐户状态的代码,即。 1 =开放,2 =关闭,3 =暂停等......
现在我希望在客户表中有另一个字段来标记该帐户是否被允许暂停...某些客户如果违反交易条款将自动暂停......其他客户则不...所以相关的表格字段如下:
客户(CustomerId(PK):StatusCode:IsSuspensionAllowed)
现在这两个字段都依赖于主键,因为您无法确定特定客户的状态或是否允许暂停,除非您知道特定客户,当然当IsSuspensionAllowed字段设置为YES时,客户应该永远不会有StatusCode 3(暂停)。
从上面的表格设计来看,除非在我的表格中添加了支票约束,否则可能会发生这种情况。我无法看到如何将另一个表添加到关系设计中以强制执行此操作,因为它仅在IsSuspensionAllowed设置为YES且StatusCode设置为3时两者彼此依赖的情况下。
所以经过我冗长的解释后,我的问题是:这是一个规范化问题吗?我没有看到一个会强制执行此操作的关系设计......或者它实际上只是一个应该通过检查强制执行的业务规则约束和桌子实际上仍然正常化。
干杯,
史蒂夫
答案 0 :(得分: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时,不允许说“暂停”的状态是没有意义的?使用您的数据时,不允许的状态为StatusCode = 3 and IsSuspensionAllowed = 0
?