2

我有一个关于我正在设计并确保它被规范化的数据库的快速问题......

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

现在我想在客户表中有另一个字段来标记是否允许暂停帐户...某些客户如果违反交易条款将被自动暂停...其他人则不会...所以相关表字段将如下所示:

客户 (CustomerId(PK):StatusCode:IsSuspensionAllowed)

现在这两个字段都取决于主键,因为除非您知道特定客户,否则您无法确定特定客户的状态或是否允许暂停,当然当 IsSuspensionAllowed 字段设置为 YES 时,客户不应该拥有状态代码 3(暂停)。

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

所以在我冗长的解释之后,我的问题是:这是一个规范化问题,我没有看到一个关系设计会强制执行这个......或者它实际上只是一个应该通过检查约束来强制执行的业务规则和表实际上仍然是规范化的。

干杯,

史蒂夫

4

1 回答 1

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吗?

于 2010-06-13T05:32:02.877 回答