如何为每个用户存储可变数量的语言?

时间:2014-11-17 13:13:30

标签: mysql sql

我有一个标准的用户表。现在每个用户都可以在他的个人资料中添加未知数量的语言。为每个用户存储语言的最佳方法是什么?我只想查询一次来获取用户及其所有相应的语言。什么是最好的设计?

示例:

User
====

id    name    
----------
99    peter


Languages
=========

id    userid    lang
-------------------- 
44    99        en
45    99        fr

3 个答案:

答案 0 :(得分:1)

这是一个多对多的关系(用户可以有多种语言,反之亦然)所以为了规范化DB你应该做一个包含两个外键的新表(称之为user_x_languages):

user_x_languages
================
user_id    lang_id
99         44
99         45

您需要从语言表

中删除userid列

然后查询应该使用连接

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;

会为用户拥有的每种语言输出一行,但是会在每行重复用户名。

你想研究数据库规范化,这是一篇非常好的非技术文章: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应该是(对于所有用户):

select name, languages(name) from users;

答案 1 :(得分:1)

您可以创建多对多关系表。像这样:

表"用户"

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

答案 2 :(得分:1)

规范化用于保存磁盘空间,即良好的规范化数据库占用的空间小于非规范化数据库,但您支付的价格是性能。请记住,更多规范化=更多连接=更多处理开销。 在我看来,你的设计(使用两个表格)很好,你可以通过一个连接轻松检索数据:

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'

尝试使用标准化数据库时,您会发现需要所有三个表来获取所需的数据。