我正在设计一个模式,其中案例可以附加许多表单,并且表单可以用于许多情况。 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 :(得分:0)
拆分两者的主要好处取决于是否会将其他字段添加到CaseForm表中。例如,假设您想要记录表格是否不完整。您可以为该效果添加不完整的位字段。现在,您有两个主要选项来检索该信息:
如果你没有拆分表,你的两个主要选项是:
出于本示例的目的,查询选项1和2在性能方面大致相同。引入非聚集索引会以多种方式增加开销。它比集群索引更简化(在这个特定的例子中可能需要更多的读取扫描),它是CaseForm将占用的额外存储空间,并且必须维护索引以更新表。选项4也将执行类似的操作,与选项2具有相同的警告。选项3将是您表现最差的,因为聚簇索引扫描将包括读取您的值字段中的所有BLOB数据,即使它只需要不完整的位确定是否返回该(案例,表格)对。
所以它确实取决于你未来的发展方向。
此外,如果您继续使用拆分方法,请考虑将CaseFormAttribute.ID转移到CaseForm,然后在CaseFormAttribute中使用CaseForm.ID作为PK / FK。这里需要注意的是,我们假设所有表格将同时插入给定案例。如果那不是真的,那么你会邀请一些页面拆分,因为你的插入有点随机,但仍然普遍增加。