1

我正在设计一个模式,其中一个案例可以附加多个表单并且表单可以用于很多情况。 Form表基本上保存了在客户端呈现的html表单的结构。提交表单时,字段的名称/值对将分开存储。如何保持名称/值属性与连接表分离如下有什么价值?数据库模式 - 多对多规范化

CREATE TABLE Case (
    ID int NOT NULL PRIMARY KEY, 
    ... 
); 

CREATE TABLE CaseForm (
    CaseID int NOT NULL FOREIGN KEY REFERENCES Case (ID), 
    FormID int NOT NULL FOREIGN KEY REFERENCES Form (ID), 
    CONSTRAINT PK_CaseForm PRIMARY KEY (CaseID, FormID) 
); 

CREATE TABLE CaseFormAttribute (
    ID int NOT NULL PRIMARY KEY, 
    CaseID int NOT NULL FOREIGN KEY REFERENCES CaseForm (CaseID), 
    FormID int NOT NULL FOREIGN KEY REFERENCES CaseForm (FormID), 
    Name varchar(255) NOT NULL, 
    Value varchar(max) 
); 

CREATE TABLE Form (
    ID int NOT NULL PRIMARY KEY, 
    FieldsJson varchar (max) NOT NULL 
); 

我是我过分复杂的架构,因为同样的多对多的关系可以通过转动CaseFormAttribute表到连接表和获得完全摆脱CaseForm表如下的实现?

CREATE TABLE CaseFormAttribute (
    ID int NOT NULL PRIMARY KEY, 
    CaseID int NOT NULL FOREIGN KEY REFERENCES Case (ID), 
    FormID int NOT NULL FOREIGN KEY REFERENCES Form (ID), 
    Name varchar(255) NOT NULL, 
    Value varchar(max) NULL 
); 

基本上我想问的是哪个更好的设计?

+0

他们都会工作,但它取决于你需要什么表。你的ERD是什么样的? –

+0

有没有比另一个更好的价值? – adam78

+0

这取决于你是否需要caseform表或不,但我不能评论,因为我不知道你的数据库设计或要求 –

回答

0

拆分两者的主要好处取决于是否将其他字段添加到CaseForm表中。例如,假设你想记录表单是否不完整。您可以添加一个未完成位字段。现在,你有获取信息的主要选项:

  1. 聚集在CaseForm索引扫描
  2. 创建于CaseForm.Incomplete非聚集索引,其中包括CaseID,FormID,并扫描该

如果你没拆表,您的两个主要选项是:

上CaseFormAttribute
  • 酶Cre
  • 聚集索引扫描在包含CaseID,FormID和扫描的CaseFormAttribute.Incomplete上查找非聚集索引
  • 对于本示例而言,查询选项1和2在性能方面大致相同。引入非聚集索引会以多种方式增加开销。它比聚集索引稍少一点(可能需要在此特定示例中扫描更多的读取),它是CaseForm将占用的额外存储空间,并且必须维护索引以更新表格。选项4也将执行类似的操作,但与选项2的警告相同。选项3将是您表现最差的执行者,因为聚簇索引扫描将包括读取“值”字段中的所有BLOB数据,即使它只需要“未完成”中的位以确定是否返回该(Case,Form)对。

    所以它确实取决于你将来朝着什么方向发展。另外,如果您使用拆分方法,请考虑将CaseFormAttribute.ID转换为CaseForm,然后在CaseFormAttribute中将CaseForm.ID用作PK/FK。这里需要注意的是,我们假设所有的表单将被同时插入给定的案例。如果这不是真的,那么你会邀请一些页面拆分,因为你的插入会有点随机,但仍然会增加。

    +0

    要求是一种情况下可以有多个附加形式但不是相同的形式。它需要是多对多的关系。那么我需要使用三列(CaseId,FormId,Name)来创建复合键吗? – adam78

    +0

    @ adam78我现在看到它 - 谢谢指出。我相应地编辑了我的答案。你的密钥是正确的,你不应该在密钥中包含名称。 – mathewb

    +0

    不,我认为你是对的 - 在我的解决方案2我最终会有重复的表单,所以我需要在该实例中添加一个唯一的键(CaseId,FormId,Name)。 – adam78