我不知道这是否是正确的地方。因为这是一个关于sql数据库设计的问题,我正在考虑数据库管理员,但因为该网站的目标是数据库专业人员(而且我绝对不是专业人士),我只是在这里发布我的问题。如果您认为这类问题有更好的地方,请指出正确的地方。
提出问题。
我正在设计一个文学作品翻译数据库。因为这涉及到人和人们往往不适应静态"数据模型我有一个非常复杂的架构。以下是关于人名的部分内容。因为涉及外国作者(特别是日语),我还有人名的音译问题。目前人和名称数据库的结构如下
让我们举个例子:
我有一个名为" Kyokutei Bakin"的人,在表意文字中翻译为曲亭马琴,在日语拼音字母中翻译为キョクテイバキン。这位作者也被称为" Takizawa Bakin" (滝沢马琴,タキザワバキン)等......
具有一对多关系的3表结构可以说明具有多个名称的人(biographical_name,pen_name,ecc ...)以及每个名称都可以有多个语音读数的事实。
这一切都很好。当我搜索某人时,我只是左键加入表并为各个字段添加OR条件。例如:
SELECT DISTINCT name.name_text, phonetic_name.name_text FROM name
LEFT JOIN phonetic_name ON (name.name_id=phonetic_name.name_id)
WHERE (name.name_text LIKE "%bak%")
OR (phonetic_name.name_text LIKE "%馬琴%");
我的问题是我希望其中一个名字成为该人的主要名称。我做的方式是添加" main_name" " person"中的列表格指向" name_id" "名称"的列表。因此,当我只想要主要名称时,我可以JOIN name ON (person.main_name=name.name_id)
。
我怀疑是:
- 交叉链接两个表是一个好习惯吗?
(这里"姓名"参考"人"在person_id上,但在同一"人"引用"名称"对于main_name)。
- 这会导致问题吗?
- 如何在这种情况下设置外键?
- 如果这太乱了,我该如何改进设计?
其他信息: 作为一个设计问题,sql实现不应该那么重要,但是如果它确实如此,我使用的是sqlite3。
答案 0 :(得分:2)
我个人会简化这样的设计:
表:person
person_id
(主键)...
表:name
name_id
(主键)name
name_type
parent_name_id
(自己的外键)person_id
(人员表的外键)表格name
具有递归关系,其中parent_name_id
包含此人的主要名称的name_id
。请注意,对于主名称name_id=parent_name_id
。在name_type
列中,您可以存储名称的类型(语音,表意文字,汉字等)。如果您希望获得纯正的第三范式,可以将name_type
进一步标准化为专用表格。
我想说这个设计的主要好处是它在查询任何类型的名称时大大简化了查询。你可以简单地运行这样的东西:
Select distinct b.person_id, b.name as main_name
From name a
Inner join name b on a.parent_name_id=b.name_id
Where a.name like ‘%...%’
此外,您可以为一个人存储任意数量的名称。
如果您想从不同类型返回多个名称,可以这样做:
Select distinct b.person_id,
b.name as main_name,
c.name as kanji_name,
d.name as katakana_name
From name a
Inner join name b on a.parent_name_id=b.name_id
Left join name c on b.parent_name_id=c.parent_name_id and c.name_type=‘kanji’
Left join name d on b.parent_name_id=d.parent_name_id and d.name_type=‘katakana’
Etc...
Where a.name like ‘%...%’