我有一个标准的用户表。现在每个用户都可以在他的个人资料中添加未知数量的语言。为每个用户存储语言的最佳方法是什么?我只想查询一次来获取用户及其所有相应的语言。什么是最好的设计?
示例:
User
====
id name
----------
99 peter
Languages
=========
id userid lang
--------------------
44 99 en
45 99 fr
答案 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'
尝试使用标准化数据库时,您会发现需要所有三个表来获取所需的数据。