Sql server 如何在关系数据库中实现1:N关系,其中一个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关系的单独表 但我必须要有一个“标准”的拼写。因此,一种拼写应该是主拼写,当显示动物行时显示,等等。其他拼写仅用于搜索(可能在输入新动物行

我必须在用于存储动物品系的MVC应用程序中实现关键字(我们首先开发数据库)。每个关键字都与动物系有M:N关系

问题是每个关键字都有一堆同义词和可选拼写。因此,如果一个动物系对免疫学家特别感兴趣,它可能会得到关键字
T细胞
。但是,利益相关者希望当用户输入
t细胞
t细胞
t细胞
、或
淋巴细胞
时可以找到该行

我创建了一个数据库模型,其中关键字的实际拼写是一个具有1:N关系的单独表

但我必须要有一个“标准”的拼写。因此,一种拼写应该是主拼写,当显示动物行时显示,等等。其他拼写仅用于搜索(可能在输入新动物行时自动完成,但这是为了将来发布)

幸运的是,规范拼写是应用程序范围内的规范拼写,用户无法选择在刚输入的动物行上显示哪一个同义词

我可以想出三种方法,但这三种方法都有一些缺点:

  • 在关键字拼写表中包括
    isCanonicalSpelling
    位。很简单,但是如果我的代码有一个bug或者有人编写了一个快速脚本来对数据库做一些事情,那么我可能最终会遇到这样的情况:同一关键字的多个或少个拼写被标记为canonical
  • 在关键字表中包括
    规范拼写
    字段。然后,规范拼写将不会写入拼写表。仍然相对容易,但不知何故,对于拼写表中没有的拼写感到不干净。交换规范和非规范拼写的代码更复杂
  • 在关键字和关键字拼写表之间建立第二个1:1的关系。从ERD的角度来看,这似乎是最好的解决方案,但我不知道如何用我正在使用的工具很好地实施它。我不知道Microsoft SQL server是否允许1:1关系,即使它允许,我也不知道如何才能使Entity Framework顺利运行,它可能需要大量代码 那么,您认为哪种解决方案是最好的?哪一个在将来会让我头痛最少,为什么?我忽略的任何解决方案都有缺点吗?有没有更好的解决办法我还没有想到


    我是在这里发布的,不是故意在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,如果您只需要规范值,您甚至不需要访问
      关键字拼写
    选项2
    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');