用单选数据存储多选数据

Joh*_*nes 3 database-design

我有一个包含一些多选字段的数据库。为简单起见,我们假设这些字段是 MatchGender 和 Interests。我希望用户能够找到匹配的人(因此性别是一个多选;他们可以选择匹配一个或两个性别)和兴趣/爱好。除了这些字段,还有几个“单选”字段,例如用户的城市、州、他们的性别等......

我试图找出存储这些数据的最佳方式,以便于搜索。我是否将多选数据存储在以逗号分隔的单个字段中?我是否将其存储在带有 UserID 的单独表中?每个的优点/缺点?

顺便说一下,这是一个 SQL Server 后端数据库,可通过 ASP Web 界面访问。

MDC*_*CCL 5

具体答案

首先,这是我个人对您的具体问题的处理方法:

我是否将多选数据存储在以逗号分隔的单个字段中?

不,我不建议您这样做。由于您有机会使用关系数据库管理系统(RDBMS),我个人认为以关系方式设计和实现您的数据库将非常方便和合理。我相信,当人们可以利用关系工具的健壮性时,没有必要使用像 CSV 这样有限的格式。如果您选择 CSV 方法,则会给项目增加不必要的复杂性。

  • 优点。CSV 格式在某些情况下有其用途,例如,在处理格式不兼容的数据的应用程序之间提供信息交换。CSV 的另一个特点是它可以通过电子表格应用程序轻松修改,例如 MS Excel 或 LibreOffice Calc。无论如何,由于您将使用 RDBMS,我认为这些事实中的任何一个都与关系平台中的数据库设计或存储无关。如果您将来需要以 CSV 格式交付某些数据,那么您可以将结构化数据导出到逗号分隔的文件中,而不会破坏数据库的可靠性。

  • 缺点。您可能已经知道,将 CSV 数据存储在单列中,您将打破First Normal Form。这样,对于非规范化数据(非简单或多值列),您将失去RDBMS 提供的许多基本技术优势,这些优势牢牢扎根于关系理论。由于许多人正确地列举了大量的问题 通过在 RDBMS 中以 CSV 格式存储数据而产生的,我只会提到您将面临数据完整性的风险(这被广泛认为是数据库最重要的属性之一),您的系统性能将大大降低减少,您最终将在您自己的应用程序中重新实现 RDBMS 本身提供的许多功能,这些功能多年来得到了极大的优化。

我是否将它存储在一个单独的表中UserID

是的,对我来说这是最好的方法,可以通过规范化在关系系统中轻松实现。

据我了解,您的规格MatchGender代表了给定User有兴趣与之取得联系的潜在合作伙伴的性别。因此,断言a User seeks one-to-many MatchGendersa MatchGender is sought by one-to-many Users是在此特定上下文中特别重要的业务规则

如果以上是正确的,那么之间存在许多一对多的关系,UserMatchGender,而这种情况是在关系数据库开发很常见。在我的建议中,我将对此方面进行建模并在下面提供一个实现示例。

  • 优点。您可以期待可预测的结果,因为您的数据库将建立在关系原则之上。您可以充分利用 RDBMS 功能,例如聚合函数、JOIN、参照完整性等。您可以防止数据冗余和全表扫描。您的数据库结构对于未来的更改或扩展将更加灵活。您可以提供在很大程度上满足客户需求的数据库性能。您的数据检索将很简单。

  • 缺点。乍一看,关系方法可能看起来有点麻烦,因为它要求数据库设计者和程序员更加自律,但随着项目的发展,这种自律会得到回报。

场景的其他相关方面

我想描述一些关于我对你的情况的理解的其他观点。这样,我认为语句a User pursues one-to-many Hobbiesa Hobby is pursued by one-to-many Users也是重要的业务规则。因此,实体User和之间也存在多对多关系Hobby,这也必须建模和实现。

我假设您将有一组Hobbies将由某种系统管理员插入到数据库中。如果是这样,则可以定义HobbyCode唯一标识 a 的给定出现的 a Hobby,您可以将其设置为此类表的有意义的PRIMARY KEY。

建模与实施建议

因此,针对你的情况,我提出以下IDEF1X数据模型:

用户兴趣 DM

然后,DDL可以从这样的数据模型中轻松导出和物理实现下一个:

CREATE TABLE Gender
(
    GenderCode      CHAR(1)  NOT NULL,
    Name            CHAR(11) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_Gender PRIMARY KEY CLUSTERED 
    (
        GenderCode ASC 
    ),
    CONSTRAINT UIX_Gender_Name UNIQUE
    (
        Name
    )
)

CREATE TABLE Hobby
(
    HobbyCode       CHAR(2)  NOT NULL,
    Name            CHAR(30) NOT NULL,
    Descriptionn    CHAR(90) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_Hobby PRIMARY KEY CLUSTERED 
    ( 
        HobbyCode ASC 
    ),
    CONSTRAINT UIX_Hobby_Name UNIQUE
    (
        Name
    )
)

CREATE TABLE UserProfile
(
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATETIME NOT NULL,
    GenderCode      CHAR(1)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_UserProfile PRIMARY KEY CLUSTERED 
    (
        UserId ASC
    ),
    CONSTRAINT UIX_UserProfile_FirstName_LastName_and_BirthDate UNIQUE
    (
        FirstName ASC,
        LastName  ASC,
        BirthDate ASC
    ),
    CONSTRAINT FK_UserProfile_Gender FOREIGN KEY 
    (
        GenderCode
    ) 
    REFERENCES Gender (GenderCode)
)

CREATE TABLE UserMatchGender
(
    UserId          INT      NOT NULL,
    GenderCode      CHAR(1)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_UserMatchGender PRIMARY KEY CLUSTERED 
    (
        UserId     ASC,
        GenderCode ASC
    ),
    CONSTRAINT FK_UserMatchGender_UserProfile FOREIGN KEY 
    (
        UserId
    )
    REFERENCES UserProfile (UserId),
    CONSTRAINT FK_UserMatchGender_Gender FOREIGN KEY 
    (
        GenderCode
    )
    REFERENCES Gender (GenderCode)
)

CREATE TABLE UserHobby
(
    UserId          INT      NOT NULL,
    HobbyCode       CHAR(2)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_UserHobby PRIMARY KEY CLUSTERED 
    (
        UserId    ASC,
        HobbyCode ASC
    ),
    CONSTRAINT FK_UserHobby_UserProfile FOREIGN KEY 
    (
        UserId
    )
    REFERENCES UserProfile (UserId),
    CONSTRAINT FK_UserHobby_Hobby FOREIGN KEY 
    (
        HobbyCode
    )
    REFERENCES Hobby (HobbyCode)
)
Run Code Online (Sandbox Code Playgroud)