Sql 简单的数据库规范化问题

Sql 简单的数据库规范化问题,sql,database,normalization,3nf,Sql,Database,Normalization,3nf,我有一个关于我正在设计并确保其规范化的数据库的快速问题 我有一个customer表,主键为customerId。它有一个StatusCode列,其中有一个反映客户帐户状态的代码,即1=打开、2=关闭、3=暂停等 现在,我想在customer表中有另一个字段,用于标记是否允许暂停帐户。。。如果某些客户违反交易条款,他们将被自动暂停交易。。。其他人不是。。。因此,相关表格字段如下所示: 客户(CustomerId(PK):状态代码:IsSuspensionAllowed) 现在,这两个字段都依赖于主

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

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

现在,我想在customer表中有另一个字段,用于标记是否允许暂停帐户。。。如果某些客户违反交易条款,他们将被自动暂停交易。。。其他人不是。。。因此,相关表格字段如下所示:

客户(CustomerId(PK):状态代码:IsSuspensionAllowed)

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

从上面的表格设计来看,除非在我的表格中添加一个检查约束,否则这种情况是可能发生的。我看不出如何在关系设计中添加另一个表来实现这一点,因为只有当IsSuspensionAllowed设置为YES,StatusCode设置为3时,这两个表才相互依赖

因此,在我冗长的解释之后,我的问题是:这是一个规范化问题吗?我没有看到一个关系设计能够实现这一点。。。或者它实际上只是一个业务规则,应该使用检查约束强制执行,并且表实际上仍然是规范化的

干杯


史蒂夫:是的,这是可能的。您可以使用检查约束和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 )
        , ....
        )
创建客户表(
CustomerId非空主键
,状态代码int不为空
,IsSuspensionAllowed int非空默认值(1)
,约束检查客户问题允许
检查(IsSuspensionAllowed In(0,1))
,Constraint CK_Customer_StatusCodeRange
检查(状态代码介于0和???之间)
,约束CK\u Customer\u statuscode有效
支票(箱)
当StatusCode=3且IsSuspensionAllowed=1时,则为0
其他1
结束=1)
, ....
)
你没有提到PK的数据类型,所以我只是插入了一个占位符。如果您使用的是SQL Server,则可以使用bit列代替上面提到的
int
并检查约束(
bit
不是ANSI规范的一部分)

这是一个很好的例子,说明诸如状态代码之类的代理键并不总是工作正常。最好让字符串值表示状态代码,在这种情况下,当StatusCode='Suspended'和IsSuspendedAllowed=0…时,case语句将读取

从规范化的角度来看,我没有看到任何错误。是否允许暂停是特定于客户的一个属性,而不是另一个属性。您使用check约束所说的是,属性值的某些状态不能存在,这很好


顺便说一句,当IsSuspensionAllowed=0时,如果说“Suspended”的状态是不允许的,那就没有意义了?使用您的数据,不允许的状态不应该是
StatusCode=3且IsSuspensionAllowed=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 )
        , ....
        )
创建客户表(
CustomerId非空主键
,状态代码int不为空
,IsSuspensionAllowed int非空默认值(1)
,约束检查客户问题允许
检查(IsSuspensionAllowed In(0,1))
,Constraint CK_Customer_StatusCodeRange
检查(状态代码介于0和???之间)
,约束CK\u Customer\u statuscode有效
支票(箱)
当StatusCode=3且IsSuspensionAllowed=1时,则为0
其他1
结束=1)
, ....
)
你没有提到PK的数据类型,所以我只是插入了一个占位符。如果您使用的是SQL Server,则可以使用bit列代替上面提到的
int
并检查约束(
bit
不是ANSI规范的一部分)

这是一个很好的例子,说明诸如状态代码之类的代理键并不总是工作正常。最好让字符串值表示状态代码,在这种情况下,当StatusCode='Suspended'和IsSuspendedAllowed=0…
时,case语句将读取

从规范化的角度来看,我没有看到任何错误。是否允许暂停是特定于客户的一个属性,而不是另一个属性。您使用check约束所说的是,属性值的某些状态不能存在,这很好


顺便说一句,当IsSuspensionAllowed=0时,如果说“Suspended”的状态是不允许的,那就没有意义了?使用您的数据,不允许的状态不应该是
StatusCode=3且IsSuspensionAllowed=0

谢谢,我正在进行规范化,而“整把钥匙都是钥匙”的事情让人有些怀疑。我觉得状态和IsSuspended之间可能存在一种过渡依赖关系。正如您所提到的,每个属性都是特定于客户的。我承认我喜欢在大多数情况下使用代理键进行标准化。我通常只会在有一个已经制定好的标准时,比如货币,或者在代表多对多关系的表格中。不过,我接受你关于提高机上可读性的评论