可以包含具有多种不同拼写的单词的字典的表格设计

Posted

技术标签:

【中文标题】可以包含具有多种不同拼写的单词的字典的表格设计【英文标题】:Table design for a dictionary that can have words with many different spellings 【发布时间】:2015-11-20 13:16:16 【问题描述】:

我正在 Microsoft Access(2013 版)中开发一个小型的个人字典数据库。英语中有很多单词有两个甚至更多的拼写。但实际上,三个拼写的单词并不多,更不用说四个拼写了。尽管如此,它们确实存在。示例包括 aerie/aery/eyrie/eyry(一个有四个拼写的单词)和 ketchup/catsup/catchup(三个拼写的单词)。更不用说英语实际上充斥着具有两种拼写的单词。每个人都知道(英国和英国拼写系统之间的差异立即浮现在脑海中)。所以,我需要以这样一种方式设计我的桌子,使设计没有重大缺陷。我将逐步解释数据库应该是什么样子,并介绍我在当前设计中发现的问题。所以,我们开始吧。

显然,所有单词都应该存储在同一张表中。而且我不会包括设计的不相关方面,例如可能是表的一部分的其他列(实际上,数据库要复杂得多)。让我们专注于最重要的部分。以下是带有一些预填充示例数据的 Words 表的外观:

+---------+-----------+
| word_id | word      |
+---------+-----------+
|       1 | ketchup   |
|       2 | catsup    |
|       3 | catchup   |
|       4 | moneyed   |
|       5 | monied    |
|       6 | delicious |
+---------+-----------+

要跟踪一组相同但拼写不同的单词,明智的做法是选择其中一个作为主词,另一个作为子词。这是向您展示我的设想的图表(这里,ketchupmoneyed 是主要词,所有其他子词):

所有这些信息都将放在一个新表中,我们将其称为 Alternative Spellings 表(列 word_idalt_spell_word_id成为表的复合主键的一部分):

+---------+-------------------+
| word_id | alt_spell_word_id |
+---------+-------------------+
|       1 |                 2 |
|       1 |                 3 |
|       4 |                 5 |
+---------+-------------------+

这是 Access 的“关系”面板中的所有内容(请注意,我已在 Words 表的 word_id 列和 word_id Alternative Spellings 表的 em> 列,并勾选 Cascade Delete Related Records 选项):

虽然简单直接,但这是迄今为止我能想到的唯一设计。我认为这基本上可以做到。这很简单。然而,这种设计存在三个问题:

1:这不是一个严重的问题,但无论如何我还是想听听你的想法。每次我在 Word Details 表单中查找一个单词以查看它时,我都必须遍历整个 Alternative Spellings 表以查看它是否有其他与之相关的拼写或者如果它是一个子词。因此,我必须同时搜索 word_idalt_spell_word_id 列。每次我想检查它的细节时,这个过程将成为数据库中每个单词的讨论场所。一种可能的解决方案是在 Words 表中创建一个额外的布尔列,该列将跟踪单词是否具有替代拼写。这将指示我们在 Word Details 表单中打开它时是否应该扫描 Alternative Spellings 表。这就是它的样子:

+---------+-----------+------------------+
| word_id | word      | has_alt_spelling |
+---------+-----------+------------------+
|     101 | ketchup   | yes              |
|     102 | catsup    | no               |
|     103 | catchup   | no               |
|     104 | moneyed   | yes              |
|     105 | monied    | no               |
|     106 | delicious | no               |
+---------+-----------+------------------+

我认为这是一个很好的设计,但是,正如我所说,我非常想听听您对此的看法:问题/不是问题?你的解决方案?

2:另一个更严重的问题与主键有关。 word_idalt_spell_word_id 当然应该是复合主键的一部分。我们不希望表中有重复的行。我们都明白这一点。不是问题。但是,当我们尝试在 Words 表和 Alternative Spellings 表之间强制执行引用完整性时,会发生这种情况(参见上面的屏幕截图)。一切都很好,除了现在我们可以将一个单词与一个不存在的单词的 id 关联起来,并且数据库不会抱怨,因为例如,word_id 中的最后一条记录有 4,即确实,我们确实在 Words 表中有一条 id 为 4 的记录,但是没有办法对 alt_spell_word_id 列施加任何类型的约束。我们可以在里面放任何废话:

+---------+-------------------+
| word_id | alt_spell_word_id |
+---------+-------------------+
|       1 |                 2 |
|       1 |                 3 |
|       4 |                 5 |
|       4 |             34564 |
+---------+-------------------+

我认为这破坏了数据库模式的引用完整性,因此是一个严重的问题。您想提供什么样的解决方案?

3:这种设计的另一个问题是,如果我们想从Words表中删除某个单词,删除会通过Alternative Spellings表级联删除所有相关记录都在那里,这很好,但这里有一个问题:因为我们同意数据库中的不同单词实际上可以只是一个具有不同拼写的单词,所以它们都应该与主要单词一起删除。但就目前的情况而言,这不会发生。例如,如果我要删除 Words 表中的 ketchup,那么 Alternative Spellings 表中的所有相关记录都会被删除。美好的。但我们确实会得到两个悬空记录,catchupcatsup——它们不能单独存在,因为它们是 ketchup 所在组的一部分em> 是主要词,但现在已被删除:

+---------+-----------+
| word_id | word      |
+---------+-----------+
|       2 | catsup    |
|       3 | catchup   |
|       4 | moneyed   |
|       5 | monied    |
|       6 | delicious |
+---------+-----------+

+---------+-------------------+
| word_id | alt_spell_word_id |
+---------+-------------------+
|       4 |                 5 |
+---------+-------------------+

如果你想玩,这里是the actual database(简化版)。

提前谢谢大家。

【问题讨论】:

【参考方案1】:

1) 对于1,如果您向数据库添加索引,这可能不是一个大问题(因为您查找一个单词然后加入以获得替代单词会很快) .但是,如果一个子词只能有一个父词,那么您不需要额外的表:

单词表可以是:

+---------+-----------+------------------+
| word_id | word      | parent_word_id   |
+---------+-----------+------------------+
|     101 | ketchup   |                  |
|     102 | catsup    | 101              |
|     103 | catchup   | 101              |
|     104 | moneyed   |                  |
|     105 | monied    | 104              |
|     106 | delicious |                  |
+---------+-----------+------------------+

一个单词及其子项的查询将是:

select wordGroup.word 
from word w join word wordGroup on 
    (w.word_id = wordGroup.parent_word_id 
     or wordGroup.word_id = w.word_id) 
where w.word = your_word;

查询一个词和相关词,不管它是否是子词:

select wordGroup.word 
from word w join word wordGroup on 
    (w.word_id = wordGroup.parent_word_id 
    or wordGroup.word_id = w.word_id) 
where wordGroup.word_id = your_word;

2 正确的做法是在表上放置外键约束(参照约束)。在我的 1 示例中,parent_word_id 将具有对 word(word_id) 的引用约束。对于您的示例,alt_spell_word_id 将对单词表和 word_id 具有引用约束。然后,您可以对 word_id 和 alt_spell_id 的组合设置唯一约束。请参阅(关于访问限制):https://msdn.microsoft.com/en-us/library/bb177889(v=office.12).aspx

3 我认为删除主要单词在您的设计中存在含义问题。删除主词并保留分组是什么意思?理论上,你需要做一系列的操作: 1-决定一个新的主词; 2-删除旧的。这几乎适用于任何设计,包括主要词。

另一种选择是没有主词但有组。这将 db 设计从主词和其他词之间的一对多关系更改为词之间的多对多关系。在这种情况下,删除很容易,因为您只需将所有与单词的关联从 word_groups 表中级联出来。

生成的表格将是:

单词:

+---------+-----------+
| word_id | word      |
+---------+-----------+
|     101 | ketchup   |
|     102 | catsup    |
|     103 | catchup   |
|     104 | moneyed   |
|     105 | monied    |
|     106 | delicious |
+---------+-----------+

word_groups:

+---------+-----------+
| word_id |sibling_word_id      
+---------+-----------+
|     101 | 102       |
|     101 | 103       |
|     102 | 101       |
|     102 | 103       |
|     103 | 101       |
|     103 | 102       |
|     104 | 105       |
|     105 | 104       |
+---------+-----------+

外键约束保护参照完整性,而索引可以加快查找速度。

【讨论】:

【参考方案2】:

我想我会使用一个模型,其中另一个表定义word_spelling_groups,因此对于每个可能与“番茄酱”含义相同的单词,此表中都有一个与 word_spelling_group 值相同的条目“番茄酱”的值为word_spelling_group

这样做的一个好处是一个单词可以是多个拼写组的成员,以防它仅在特定含义的上下文中具有替代拼写(我很难举个例子)。

【讨论】:

以上是关于可以包含具有多种不同拼写的单词的字典的表格设计的主要内容,如果未能解决你的问题,请参考以下文章

具有多种变体的 Foreach 字符串替换

NLP_Stanford课堂拼写校正

具有多种功能的产品的数据库设计

我的拼写检查器无法正确比较单词

电商通用型商品中心设计

如何通过代码拼写检查将所有未知单词添加到字典中,或者当语言不是英语时忽略它们?