2012-04-06 33 views
4

我想知道什么是最好的存储方式,例如languagesuser表格中,当用户可以根据自己的意愿选择尽可能多的语言,并希望而不使用序列化数据,因为该字段将被严格搜索。Mysql在表格中存储任意数量的值的最佳方式

我想limtating条目的数量,为为例maximun 4语言,在user表中有语言1,LANG2 ..

有没有更好的方式来实现这一目标?

回答

4

它被称为database normalization。具体而言,您需要映射一个"Many to Many" association

您需要3个表格。

User(id, name) 
Language (id, language_name) 
User_Language(id,id_user,id_language) 

要获取所有语言的用户ID 3:

SELECT l.language_name 
FROM User u 
JOIN user_language ul ON (u.id=ul.id_user) 
JOIN Language l ON (l.id = ul.id_language) 
WHERE u.id = 3 

编辑:

两件事情是很重要的注意@silkAdmin。第一个,就像@ BryceAtNetwork23指出的那样,不需要在User_Language表上添加一个id。第二个是,你应该了解joins,特别是MySQL Joins(因为SQL在不同的数据库引擎中倾向于不同)。你挖一点点之后,你就可以看到,在之前的查询加入用户表也没有必要,也可以简化为:

SELECT l.language_name 
FROM user_language ul 
JOIN Language l ON (l.id = ul.id_language) 
WHERE ul.user_id = 3 

我又补充它的第一个答案,使对你来说更容易。

为什么使用的语言表

我的回答只是反映我会做到这一点。有很多方法来实现要求的东西。说,我解释我自己。

让我们在极端思考。第一个极端是将语言存储在用户表中,如上所述。例如,我们可以有一列,并用分号分隔这些值。像这样的东西

User: (1, "John", "spanish;english;japanese") 

这样做的好处是你不需要任何连接。鉴于你的用户的ID,你可以得到的语言。缺点是,这将是非常痛苦的搜索。如何让所有用户使用语言“西班牙语”? (这里的底线是你不能索引你的数据)。另一个缺点是,过时使用磁盘空间。在数据库和规范化发明的时候,磁盘空间确实很昂贵。因此,存储此:

User: (1, "John", "spanish;english;japanese") 
User: (2, "Mary", "spanish;english") 

这是不能容忍的东西。所以,有些人来了,说:“嘿,让我们使用IDS,所以,我们可以把它变成”:

User: (1, "John", "1;2;3") 
User: (2, "Mary", "1;2") 

Language (1,"spanish") 
Language (2,"english") 

10.000用户和语言仅有几百,这是对磁盘使用一个巨大的进步(也许在我们这个时代,这不再是真的,我会在稍后谈到)。这解决了磁盘问题,但我们仍然有搜索问题。同样,如何让所有用户使用语言“西班牙语”?那么,利用这个设计,你应该遍历用户表并获取语言列,将它分成“;”并查找ID 1.

这就是为什么我们开始使用的方法,我之前向您展示。

所以,到目前为止,一切顺利。相当不错的解释;)

大免责声明

正如我以前说过的,有几种方法可以做到这一点。这取决于你的情况,你想达到什么目的。如果您想根据该专栏进行搜索(例如,给我说英语的用户),您应该考虑我在答复顶部告诉您的设计。

现在有数据解决方案的“新浪潮”是被称为无SQL数据库(有异),尝试非规范化的数据。如果你担心模式的过度规范化,你应该看看这个。我建议你使用MongoDB和CouchDB,因为这些比较容易。

关于加入

不要担心2加入了性能。如果你有性能问题,那不是这个。数据库引擎是为此创建的。有了良好的内存缓存和索引优化,它应该可以顺利运行。

+0

其实,你就不需要在USER_LANGUAGE一个ID字段。字段id_user和id_language(一起作为连接的键)将确保唯一性。 – Aaron 2012-04-06 17:38:55

+0

是的,但这是一个很好的做法。我不需要那个连接中的用户表,但为了解释我添加它。 – santiagobasulto 2012-04-06 18:06:40

+0

@santiagobasulto感谢您的详细解答。我知道如何使用连接,但通过保持性能,我尝试只有在没有其他方式时才使用它们。虽然我很好奇为什么要使用语言表?不应该用户语言表足够了(用enum字段替换id_language) – silkAdmin 2012-04-07 01:24:08

1

是的,最好的方法是使用列lang_iduser_id的附加表。您可以存储任意数量的用户/语言关联(每行一个)。

0

我认为你应该考虑有两张桌子。一个与users和一个与languages。维护起来更容易,对这些表执行joins更容易。

1

创建表user_languages

user_id int, 
language_id int, 

与约束:

PRIMARY KEY (user_id, language_id), 
FOREIGN KEY (language_id) REFERENCES language(id), 
FOREIGN KEY (user_id) REFERENCES users(id) 

有了这样的限制,用户可以根据需要分配有尽可能多的语言。

1

我认为实现这一目标的最好办法,就是有一个用户表USER_LANGUAGES表和语言表。这样,用户可以拥有任意数量的语言。

USER 
user_id int 
user_name varchar 

USER_LANGUAGES 
user_id int 
lang_id int 

LANGUAGES 
lang_id int 
lang_name varchar 

USER存储基于用户的字段。语言存储每种特定语言(英语,德语等)的数据。 USER_LANGUAGES存储哪些用户知道哪种语言的关联。

相关问题