我有一个标准的用户表。现在每个用户都可以在他的个人资料中添加未知数量的语言。为每个用户存储语言的最佳方式是什么?我只想询问一次以获取用户及其所有相应的语言。什么是最好的设计?如何为每个用户存储可变数量的语言?
例子:
User
====
id name
----------
99 peter
Languages
=========
id userid lang
--------------------
44 99 en
45 99 fr
我有一个标准的用户表。现在每个用户都可以在他的个人资料中添加未知数量的语言。为每个用户存储语言的最佳方式是什么?我只想询问一次以获取用户及其所有相应的语言。什么是最好的设计?如何为每个用户存储可变数量的语言?
例子:
User
====
id name
----------
99 peter
Languages
=========
id userid lang
--------------------
44 99 en
45 99 fr
这是一个多对多的关系(一个用户可以有许多语言,反之亦然),所以正常化DB你应该做包含两个外键的新表(称之为user_x_languages ):
user_x_languages
================
user_id lang_id
99 44
99 45
你需要从你的语言表中删除用户ID列
查询应再使用连接
select name lang from user u
join user_x_languages x on u.id = x.user_id
join languages l on x.lang_id = l.id
where u.id = 99;
这会为用户所拥有的每种语言输出一行,但它会重复每行的用户名。
你想看看DB正常化,一个非常漂亮的非技术性的文章是这样的:A Simple Guide to Five Normal Forms in Relational Database Theory
以下this线程的建议有关返回一行,程序会像(我可能已经改变了表和列名从原来的一点点):
delimiter //
Create function languages (p_user varchar(30))
returns text
begin
DECLARE ret_val TEXT;
select GROUP_CONCAT(lang) into ret_val
from Users u
join user_x_lang x on u.user_id = x.user_id
join Lang l on x.lang_id = l.lang_id
where u.name = p_user;
return ret_val;
end//
delimiter ;
现在的选择应该是(对所有用户):
select name, languages(name) from users;
您可以创建一个多对多的关系表。就像这样:
表 “用户”
user_id | name
99 peter
100 tim
表 “语言”
language_id | language
44 en
45 fr
表 “User_to_language”
User_id | Language_id
99 45
100 45
100 46
或者,如果你需要大量的用户属性在将来,您可能会使用类似于: 表User_attributes
user_id | attribute | value
46 'lang' 'en'
而且,这可能对您有用:Database normalization
正常化是用来保存磁盘空间,即一个好的规范化的数据库需要较少的空间比非标准化的,但是你付出的代价是性能。请记住更多的标准化=更多的联合=更多的处理开销。 在我看来,(使用两个表)你的设计是好的,你可以很容易地检索数据单个连接:
select * from Usrs u join Languages l on u.id = l.usrid
now some sample queries which will come in application code
--select those users who speak 'en' then
select * from Usrs u join Languages l on u.id = l.usrid
where l.lang = 'en'
--peter speaks which languages
select * from Usrs u join Languages l on u.id = l.usrid
where u.name = 'peter'
尝试用一个标准化的数据基础相同,你会发现,你需要所有三个表获得所需的数据。
您需要第三张表用户和语言'new_table(uderid,languageid)'之间的关系并保留'languages(id,lang)' –
用户和语言表可以与'id'和'userid'列关联在上面的设计中,不需要第三张表。我认为这很好。 –
是的,我会这样做,但这不是我要求的点 – Patrick