Sql server 如何在关系数据库中实现1:N关系,其中一个N是特殊的?
我必须在用于存储动物品系的MVC应用程序中实现关键字(我们首先开发数据库)。每个关键字都与动物系有M:N关系 问题是每个关键字都有一堆同义词和可选拼写。因此,如果一个动物系对免疫学家特别感兴趣,它可能会得到关键字Sql server 如何在关系数据库中实现1:N关系,其中一个N是特殊的?,sql-server,entity-framework,database-design,entity-relationship,Sql Server,Entity Framework,Database Design,Entity Relationship,我必须在用于存储动物品系的MVC应用程序中实现关键字(我们首先开发数据库)。每个关键字都与动物系有M:N关系 问题是每个关键字都有一堆同义词和可选拼写。因此,如果一个动物系对免疫学家特别感兴趣,它可能会得到关键字T细胞。但是,利益相关者希望当用户输入t细胞、t细胞、t细胞、或淋巴细胞时可以找到该行 我创建了一个数据库模型,其中关键字的实际拼写是一个具有1:N关系的单独表 但我必须要有一个“标准”的拼写。因此,一种拼写应该是主拼写,当显示动物行时显示,等等。其他拼写仅用于搜索(可能在输入新动物行
T细胞
。但是,利益相关者希望当用户输入t细胞
、t细胞
、t细胞
、或淋巴细胞
时可以找到该行
我创建了一个数据库模型,其中关键字的实际拼写是一个具有1:N关系的单独表
但我必须要有一个“标准”的拼写。因此,一种拼写应该是主拼写,当显示动物行时显示,等等。其他拼写仅用于搜索(可能在输入新动物行时自动完成,但这是为了将来发布)
幸运的是,规范拼写是应用程序范围内的规范拼写,用户无法选择在刚输入的动物行上显示哪一个同义词
我可以想出三种方法,但这三种方法都有一些缺点:
isCanonicalSpelling
位。很简单,但是如果我的代码有一个bug或者有人编写了一个快速脚本来对数据库做一些事情,那么我可能最终会遇到这样的情况:同一关键字的多个或少个拼写被标记为canonical李>
规范拼写
字段。然后,规范拼写将不会写入拼写表。仍然相对容易,但不知何故,对于拼写表中没有的拼写感到不干净。交换规范和非规范拼写的代码更复杂李>
我是在这里发布的,不是故意在dba.stackexchange上发布的。我知道从ERD的角度来看,第三种解决方案是最好的,但我想知道哪种解决方案将允许最简单的应用程序级代码,而不会有太多数据不一致的风险 简单地说:同义词不属于(仅)列表中。根据定义,项目列表几乎是相同类型项目的集合。但是,有两种同义词在某些场景中功能不同(在其他场景中功能相同) 我不知道有任何默认解决方案,但我可以想出很多选择:
- 是否总是有一个“主要”同义词?永远不会少,永远不会多?我建议在
项中添加一列(nvarchar),输入正确的拼写。如果用户随后使用同义词,则可以轻松访问类似于关键字
的内容。(如果它有助于同义词搜索算法,您仍然可以在下面添加一个同义词条目,其中包含完全相同的单词。要保存的数据稍微多一些,但在匹配所有可能的值时,您可以轻松地在列表上迭代。)同义词实体.ParentKeyword.Name
- 是否可能没有正确的名称设置?还是多重?(例如,美国/英国英语)在这些场景中,我会在同义词表中选择一个额外的列来放置布尔值(
)。如果您有多个区域性设置,则可能需要为所选语言找到正确的一个(例如,定义区域性设置的第二列)。或者您可以只使用IsCorrectSpelling
MultipleSynonyms.FirstorDefault(word=>word.IsCorrectSpelling)
但是当谈到选择正确的拼写时,它们显然是不同的,您需要一种方法来区分这两种同义词(即,添加一个布尔值,或在另一个位置(如
关键字
表)中注意正确的拼写)
因此,你通常会想寻找一种方法,你可以把他们都当作。大多数情况下,这意味着您必须引入某种形式的继承、在数据库中复制数据等。您需要额外的复杂性。我选择与自然键结合使用的选项3:
CREATE TABLE Keyword (
ID INT PRIMARY KEY,
CanonicalSpelling VARCHAR(100)
);
CREATE TABLE KeywordSpelling (
ID INT,
Spelling VARCHAR(100),
PRIMARY KEY (ID, Spelling)
);
ALTER TABLE Keyword
ADD FOREIGN KEY (ID, CanonicalSpelling)
REFERENCES KeywordSpelling (ID, Spelling);
INSERT INTO Keyword VALUES (1, NULL);
INSERT INTO KeywordSpelling VALUES (1, 'T-Cells');
INSERT INTO KeywordSpelling VALUES (1, 't-cell');
INSERT INTO KeywordSpelling VALUES (1, 't cell');
INSERT INTO KeywordSpelling VALUES (1, 't Zelle');
INSERT INTO KeywordSpelling VALUES (1, 'lymphocyte');
UPDATE Keyword SET CanonicalSpelling = 'T-Cells' WHERE ID = 1;
请注意,CanonicalSpelling
字段是KeywordSpelling
表中已经存在的值的副本。这与选项2不同,它只有一个独立的值
乍一看,复制似乎是多余的,但请记住,DBMS将始终防止它因FK而“悬空”
- 这样,您就可以继续以通用方式查询
,并确信它包含所有值,包括规范值关键字拼写表
- OTOH,如果您只需要规范值,您甚至不需要访问
关键字拼写
CREATE TABLE Keyword (
ID INT PRIMARY KEY,
CanonicalSpelling VARCHAR(100) NOT NULL
);
CREATE TABLE KeywordSpelling (
ID INT,
Spelling VARCHAR(100),
PRIMARY KEY (ID, Spelling)
);
ALTER TABLE Keyword
ADD FOREIGN KEY (ID, CanonicalSpelling)
REFERENCES KeywordSpelling (ID, Spelling)
DEFERRABLE INITIALLY DEFERRED;
INSERT INTO Keyword VALUES (1, 'T-Cells');
INSERT INTO KeywordSpelling VALUES (1, 'T-Cells');
INSERT INTO KeywordSpelling VALUES (1, 't-cell');
INSERT INTO KeywordSpelling VALUES (1, 't cell');
INSERT INTO KeywordSpelling VALUES (1, 't Zelle');
INSERT INTO KeywordSpelling VALUES (1, 'lymphocyte');