如何为用户和配置文件场景建模

时间:2012-06-22 09:00:30

标签: sql-server database sql-server-2008 database-design

我需要为用户和关联的个人资料建立一个场景模型。

要求:

用户必须拥有必填个人资料(ProfileA),用户才能可选拥有商家资料(ProfileB)。

用户每个配置文件类型只能关联1个配置文件。

这里有关于DataBase设计的想法,我很乐意在Idea B中使用Nullable FK,提出您的意见和想法。

如果您还有替代建模解决方案,请与我分享。提前谢谢。

IDEA A:

Users
------------------
UserID   PK

ProfilesA
------------------
UserID   PK FK 

ProfilesB
------------------
 UserID   PK FK

IDEA B(使用Nullable FK):

Users
------------------
UserID     PK
ProfileAId  NULL    FK
ProfileBId  NULL    FK

ProfilesA
------------------
ProfileAId   PK

ProfilesB
------------------
ProfileBId   PK FK

1 个答案:

答案 0 :(得分:1)

IDEA A 不会强制执行ProfileA

IDEA B 可以,假设User.ProfileAId为非NULL,但这会引入循环FK,只能解决延迟约束(MS SQL Server不支持)。除此之外,您还需要User.ProfileBId上的UNIQUE约束,以防止不同用户共享相同的ProfileB(这需要额外的索引,并且每个新索引都会产生一定的开销,特别是如果您打算使用clustering)。


由于我们处理的是“1:1”(UserProfileA)和“1:0或1”(UserProfileB)关系,可能只是将所有内容放在同一个表中,然后使用NOT NULL与NULL约束来要求ProfileA而不是仅允许ProfileB

User
------------------
UserID PK

ProfileARequiredField1  NOT NULL
ProfileARequiredField2  NOT NULL
ProfileARequiredField3  NOT NULL (...)
ProfileAOptionalField1  NULL
ProfileAOptionalField2  NULL
ProfileAOptionalField3  NULL (...)

ProfileBRequiredField1  NULL
ProfileBRequiredField2  NULL
ProfileBRequiredField3  NULL (...)
ProfileBOptionalField1  NULL
ProfileBOptionalField2  NULL
ProfileBOptionalField3  NULL (...)

-- For ProfileB, if one required field is present, all must be present,
-- and optional fields are allowed only if required ones are present.
CHECK (
    (
        ProfileBRequiredField1 IS NULL AND 
        ProfileBRequiredField2 IS NULL AND 
        ProfileBRequiredField3 IS NULL AND
        ProfileBOptionalField1 IS NULL AND
        ProfileBOptionalField2 IS NULL AND
        ProfileBOptionalField3 IS NULL
    )
    OR (
        ProfileBRequiredField1 IS NOT NULL AND 
        ProfileBRequiredField2 IS NOT NULL AND 
        ProfileBRequiredField3 IS NOT NULL
    )
)

或者,将ProfileA字段保留在User中,但将ProfileB字段移至单独的表格中,就像您在IDEA A中所做的那样(IDEA不需要复杂化) B)。但是,NULL存储很便宜,您可以使用filtered indexes从索引中排除NULL,因此这可能不值得。