多对多 - 结表

时间:2011-06-11 14:16:38

标签: database database-design many-to-many

我正在做这个设计。用户可以说一种或多种语言(限制为五种)。第一语言是本地语言,其他语言是流利的。

user 1 speak 3 languages

    user_id|first language|secondlanguage|thirdlanguage|fourthlanguage| fifthlanguage 
    1        english (1)     franch(2)    portuguese (3)      null           null 

enter image description here

您对此计划有何看法? 听起来有点奇怪,或者这是正确的方法吗?

3 个答案:

答案 0 :(得分:3)

这个问题的答案实际上取决于它。关系纯粹主义者会说这是一个重复的群体,这是一个糟糕的设计,而快速和肮脏的人群会说,“如果你只是支持5种语言,那么就去做”。但是,真的 - 你怎么能确定你永远只支持5种语言?你会做什么样的询问?想象一下,你想找到所有说英语的人 - 你的疑问将是:

select * from single_user_has_spoken_languages where lang1 = @englishID or lang2 = @englishID or... etc

如果你想找到会说英语和法语的人,那么你的where子句会再次增长。如果您添加第6种语言,则每个查询都必须更改。

考虑替代方案:

select distinct UserID from single_user_has_spoken_languages where langID = @englishID

一旦你停下来思考你的查询将如何运作,好的设计就会变得更加清晰。

答案 1 :(得分:2)

我会将语言规范化。

因此,例如(为简洁省略了非键列):

Language Table
id:  INT

Single_User Table
id:  INT

User_Language Table
user_id: INT
language_id: INT
language_num:  SMALLINT

您可以在user_id,language_id以及user_id,language_num上设置唯一约束,以确保不会重复。您还可以将language_num上的检查约束设置为1到5之间,以确保只选择5种语言。

您还可以选择添加代理键,以便更轻松地引用行。

答案 2 :(得分:1)

这是“正确”或“规范化”设计的“非规范化”形式,它将有一个单独的表来存储具有流利顺序列的语言,即:

Table User: User_ud, name, etc
Table Language: user_id, fluency, name

您的方法通常用于性能原因,但通常在设计阶段应避免使用。

考虑您的设计如何处理添加更多语言位置,或者存储语言的语言。标准化设计可以轻松处理。你接近不了。