Sql 针对多种实体类型的最佳数据库设计
我正在开发一个web应用程序,我必须设计它的数据库。有一部分对我来说不是很简单,所以经过一些思考和研究,我有了很多想法。但这两种方法似乎都不完全合适,所以我不确定应该实施哪种方法以及为什么 简化问题如下所示: 我有一位餐桌老师。根据与各自领域和学科的关系,有两种类型的教师:Sql 针对多种实体类型的最佳数据库设计,sql,django,sqlite,database-design,foreign-key-relationship,Sql,Django,Sqlite,Database Design,Foreign Key Relationship,我正在开发一个web应用程序,我必须设计它的数据库。有一部分对我来说不是很简单,所以经过一些思考和研究,我有了很多想法。但这两种方法似乎都不完全合适,所以我不确定应该实施哪种方法以及为什么 简化问题如下所示: 我有一位餐桌老师。根据与各自领域和学科的关系,有两种类型的教师: 与某一领域相关的教师,该领域与某一类别相关 与某个领域无关,但与某个类别直接相关的教师 我最初的想法是有两个可为空的外键,一个指向表字段,另一个指向表类别。但是在这种情况下,我如何确保一个是空的,另一个不是空的 另一个想法是
我正在使用Django和SQLite db开发应用程序。好的,你的评论让它更清晰了: 如果教师只属于一个类别,则应直接将其保存在教师表中: 其次,每个教师都属于“一个或零个”字段。如果这是确定的,您应该使用一个可为空的FieldID列。此选项已设置或保持为空
Category (CategoryID, Name, ...)
Field (FieldID,Name,...)
Teacher (TeacherID,FieldID [NULL FK],CategoryID [NOT NULL FK], FirstName, Lastname, ...)
备注:这与我上次回答的映射表几乎相同。唯一的区别是,你会有一个严格的限制,你的“完全一个”或“完全没有或一个”。。。根据我的经验,我还是更喜欢开放式的方法。使用独特的索引(包括TeacherID列)很容易实施规则。迟早你可能不得不重新构建这个
继续时,一个类别与“零个或多个”字段相关。有两种方法:
将CategoryID列添加到字段表(非空FK)。这样,您可以使用不同的CategoryId(组合唯一索引!)多次定义字段。一个类别的字段列表,您只需向字段表查询具有给定CategoryID的所有字段即可得到
在我看来,更好的是映射表类别字段。如果您强制使用一个唯一的FieldID,您将可以确保没有字段被映射两次。并在CategoryID和FieldID的组合上添加唯一索引
SELECT可以是这样的(SQL Server语法,未经测试):
这是编辑前的答案:
即使我对这个概念不是很清楚,我也会尽力帮助你
Teacher-Table: TeacherID, person's data (name, address...), ...
Category-Table: CategoryID, category title, ...
Field-Tabls: FieldID, field title, ...
您可以说,字段在所有情况下都绑定到一个类别。如果在所有情况下都是同一类别,则应在字段表中将该类别设置为FK列。如果一个字段的类别有可能因上下文的不同而有所不同,那么您不应该
与教师相同:如果教师绑定到一个类别,请在教师表中设置一个FK列,否则不设置
至少有一个映射表是最灵活的:
(SQL Server语法)
更好的概念是使用映射表FieldCategory,并通过外键将该表映射到上面的映射表。这样做可以避免无效的字段类别组合
希望这有助于…使用TeacherID、FieldID和CategoryID的映射表如何,所有这些都带有外键。使用约束检查“若设置了字段,则也必须设置类别”和索引以强制组合的唯一性。。。这允许将教师绑定到不同的字段/类别…查看答案是否符合您的目的。@Shnugo在这种设计中,确保每位教师只有一个条目的最佳方法是什么?如果我的答案有帮助,请投票支持,如果有助于您解决问题,请将其标记为已接受的答案,谢谢!每一位教师只属于一个类别。每个教师都属于一个或零个字段。每个类别由零个或多个字段组成。如果一个教师绑定到一个字段,我们可以从这个关系中获得类别。在创建ER图时,我将其绘制为三元关系,但我不知道设计模型的最佳方法。。
Teacher-Table: TeacherID, person's data (name, address...), ...
Category-Table: CategoryID, category title, ...
Field-Tabls: FieldID, field title, ...
CREATE TABLE TeacherFieldCategory
(
--A primary key to identify this row. This is not needed actually, but it will serve as clustered key index as a lookup index...
TeacherFieldCategoryID INT IDENTITY NOT NULL CONSTRAINT PK_TeacherFieldCategory PRIMARY KEY
--Must be set
,TeacherID INT NOT NULL CONSTRAINT FK_TeacherFieldCategory_TeacherID FOREIGN KEY REFERENCES Teacher(TeacherID)
--Field may be left NULL
,FieldID INT NULL CONSTRAINT FK_TeacherFieldCategory_FieldID FOREIGN KEY REFERENCES Field(FieldID)
--Must be set. This makes sure, that a teacher ever has a category and - if the field is set - the field will have a category
,CategoryID INT NOT NULL CONSTRAINT FK_TeacherFieldCategory_CategoryID FOREING KEY REFERENCES Category(CategoryID)
);
--This unique index will ensure, that each combination will exist only once.
CREATE UNIQUE INDEX IX_TeacherFieldCategory_UniqueCombination ON TeacherFieldCategory(TeacherID,FieldID,CategoryID);