多语言系统的数据库设计

简介:

之前做的项目涉及到中国大陆和纽伦新港的用户使用,也就需要做成一个多语言的系统,现在总结下其中一些经验和思考。

首先我们需要确认我们要做的系统,多语言到底是要做多少种语言,以后会不会要求增加更多的语言。比如我们做一个给中国大陆和纽伦新港使用的系统,可以确定的语言就是简体中文、繁体中文和英语,而且可以确定以后也不会增加语言。确定以后是否需要增加语言这一点很重要,决定了我们在数据库设计时,是否需要考虑多语上的扩展性。

先说下在数据库设计时,可以有以下方案实现多语:

一、为每个多语字段建立对应语言的字段列。

比如我们有一个客户表,记录了客户Id、客户名称、客户地址、客户电话等,其中客户名称和客户地址是多语的,而且需要支持简体中文、繁体中文和英语,于是我们可以将客户表设计如下:

create table Client
(
 ClientId int primary key,
 NameChs nvarchar(50),
 NameCht nvarchar(50),
 NameEng varchar(200),
 AddressChs nvarchar(50),
 AddressCht nvarchar(50),
 AddressEng varchar(200),
 TelephoneNumber varchar(50)
)

这样做的优点是容易理解,容易查询,一个客户实例对应的就是数据库中的一条数据,与普通的非多语数据库无异,而且由于没有形成新的表,所以也不需要额外的Join,所以查询效率很高:

insert into Client values(1,'工商银行','工商銀行','ICBC','中国北京','中國北京','China,Beijing','13811255555');

select *
from Client c
where c.ClientId=1

二、建立统一的翻译表,在翻译表中使用多列存储多语言,然后在实体表中外键引用翻译表。

create table Translation 
(
 TranslationId int primary key,
 TextChs nvarchar(200),
 TextCht nvarchar(200),
 TextEng varchar(200),
)

create table Client
(
 ClientId int primary key,
 NameTranId int references Translation(TranslationId),
 AddressTranId int references Translation(TranslationId),
 TelephoneNumber varchar(200)
)

这样要查询数据时,需要将Translation表JOIN2次,获得对应的Name和Address的多语。

insert into Translation values(10,'工商银行','工商銀行','ICBC');
insert into Translation values(20,'中国北京','中國北京','China,Beijing');
insert into Client values(1,10,20,'13811255555');

select c.ClientId,c.TelephoneNumber,
tn.TextChs as NameChs,tn.TextCht as NameCht,tn.TextEng as NameEng,
ta.TextChs as AddressChs,ta.TextCht as AddressCht,ta.TextEng as AddressEng
from Client c
inner join Translation tn
on c.NameTranId=tn.TranslationId
inner join Translation ta
on c.AddressTranId=ta.TranslationIdwhere 
where c.ClientId=1

以上介绍的方法都是将多语作为列输出,也就是说有多少种语言就会有多少对于的列,不利于语言的增加下面再介绍将语言以数据行的形式保存的设计方法,这种方法可以在后期任意增加语言而不改动数据库Schema.

三、将每个表中需要多语的字段独立出来,形成一个对应的多语表。

多语表外键关联原表,每个需要多语的字段在多语表中对应一列,多语表中增加“语言”字段。同样以Client表为例,那么对应的表结构是:

create table Client
(
 ClientId int primary key,
 TelephoneNumber varchar(200)
)
create table Client_MultiLanguages
(
 CLId int primary key,
 ClientId int references Client(ClientId),
 Name nvarchar(200),
 Address nvarchar(200),
 Language char(3)
)

这样的优点是便于扩展,在Schema中并没有定义具体的语言,所以如果要增加语言的话,只需要在多语表中增加一行对应的数据即可。查询也相对比较简单,执行要将原表与对应的多语表JOIN,然后跟上具体的语言作为WHERE条件,即可完成对数据的查询,比如要查询Id为1的Client对象的英语实例:

insert into Client values(1,'13811255555');
insert into Client_MultiLanguages values(1,1,'工商银行','中国北京','CHS');
insert into Client_MultiLanguages values(2,1,'工商銀行','中國北京','CHT');
insert into Client_MultiLanguages values(3,1,'ICBC','China,Beijing','ENG');

select c.*,cm.Name,cm.Address
from Client c inner join Client_MultiLanguages cm
on c.ClientId=cm.ClientId
where c.ClientId=1 and cm.Language='ENG'

四、建立统一翻译表和对应的多语表,在每个多语列指向翻译表。

create table Translation 
(
 TranslationId int primary key
)

create table Client
(
 ClientId int primary key,
 NameTranId int references Translation(TranslationId),
 AddressTranId int references Translation(TranslationId),
 TelephoneNumber varchar(200)
)


create table TranslationEntity 
(
 TranslationEntityId int primary key,
 TranslationId int references Translation(TranslationId),
 Language char(3),
 TranslatedText nvarchar(200)
)

如果要查询Id为1的Client对应的英语实例,那么脚本为:

insert into Translation values(10);
insert into Translation values(20);
insert into Client values(1,10,20,'13811255555');
insert into TranslationEntity values(1,10,'CHS','工商银行');
insert into TranslationEntity values(2,10,'CHT','工商銀行');
insert into TranslationEntity values(3,10,'ENG','ICBC');
insert into TranslationEntity values(4,20,'CHS','中国北京');
insert into TranslationEntity values(5,20,'CHT','中國北京');
insert into TranslationEntity values(6,20,'ENG','China,Beijing');


select c.ClientId,tne.TranslatedText as Name,tae.TranslatedText as Address,c.TelephoneNumber
from Client c
inner join TranslationEntity tne
on c.NameTranId=tne.TranslationId
inner join TranslationEntity tae
on c.AddressTranId=tae.TranslationId
where c.ClientId=1 and tne.Language='ENG' and tae.Language='ENG'

这个数据的插入和查询也太复杂了。同时也可以注意到在查询时根本没有用到Translation表,其实这个表只是标识每个数据实例中的多语字段,可以直接使用数据库的Sequence生成或者使用GUID,只要保证全局唯一即可。另外也可以注意到在查询时JOIN了2次TranslationEntity 表,如果一个表的多语字段比较多,比如有10个字段有多语,那么查询是就需要JOIN10次,这个效率会很低。另外还可以注意到,在WHERE条件中写了2次Language='ENG',如果多个多语字段,那么就要写多次。刚才这个查询写的不够严谨,因为不能保证Name字段和Address字段必然就有英文值,如果没有英文值会导致查询结果为空,所以正确的写法应该是:

select c.ClientId,tne.TranslatedText as Name,tae.TranslatedText as Address,c.TelephoneNumber
from Client c
left join TranslationEntity tne
on c.NameTranId=tne.TranslationId and tne.Language='ENG' left join TranslationEntity tae
on c.AddressTranId=tae.TranslationId and tae.Language='ENG' where c.ClientId=1 

实际项目中,如果我们使用了NHibernate等ORMapping工具,那么多语字段就会映射成一个集合,所以对于某种语言的实例,那么需要执行N+1次SQL查询,而不是JOIN查询,N是该对象中多语的属性个数.

目录
相关文章
|
5月前
|
前端开发 数据库
会议室管理系统源码(含数据库脚本)
会议室管理系统源码(含数据库脚本)
96 0
|
5月前
|
Java 数据库
jsp CRM客户管理系统(含数据库脚本以及文档)
jsp CRM客户管理系统(含数据库脚本以及文档)
120 10
|
6月前
|
前端开发 Java 关系型数据库
基于ssm的社区物业管理系统,附源码+数据库+论文+任务书
社区物业管理系统采用B/S架构,基于Java语言开发,使用MySQL数据库。系统涵盖个人中心、用户管理、楼盘管理、收费管理、停车登记、报修与投诉管理等功能模块,方便管理员及用户操作。前端采用Vue、HTML、JavaScript等技术,后端使用SSM框架。系统支持远程安装调试,确保顺利运行。提供演示视频和详细文档截图,帮助用户快速上手。
228 17
|
6月前
|
前端开发 Java 关系型数据库
基于ssm的超市会员(积分)管理系统,附源码+数据库+论文,包安装调试
本项目为简单内容浏览和信息处理系统,具备管理员和员工权限。管理员可管理会员、员工、商品及积分记录,员工则负责积分、商品信息和兑换管理。技术框架采用Java编程语言,B/S架构,前端使用Vue+JSP+JavaScript+Css+LayUI,后端为SSM框架,数据库为MySQL。运行环境为Windows,JDK8+Tomcat8.5,非前后端分离的Maven项目。提供演示视频和详细文档,购买后支持免费远程安装调试。
289 19
|
6月前
|
前端开发 JavaScript Java
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
249 17
|
6月前
|
前端开发 Java 关系型数据库
基于ssm的网络直播带货管理系统,附源码+数据库+论文
该项目为网络直播带货网站,包含管理员和用户两个角色。管理员可进行主页、个人中心、用户管理、商品分类与信息管理、系统及订单管理;用户可浏览主页、管理个人中心、收藏和订单。系统基于Java开发,采用B/S架构,前端使用Vue、JSP等技术,后端为SSM框架,数据库为MySQL。项目运行环境为Windows,支持JDK8、Tomcat8.5。提供演示视频和详细文档截图。
157 10
|
6月前
|
前端开发 Java 关系型数据库
基于ssm的台球厅管理系统,附源码+数据库+论文
本项目为新锐台球厅管理系统,支持管理员和会员两种角色。管理员可进行会员管理、台球桌管理、订单管理等;会员可查看台球桌、预约、购买商品等。技术框架基于Java,采用B/S架构,前端使用Vue+HTML+JavaScript+CSS+LayUI,后端使用SSM框架,数据库为MySQL。运行环境为Windows,JDK8+MySQL5.7+Tomcat8.5。提供演示视频及详细文档截图。
|
6月前
|
人工智能 Cloud Native 关系型数据库
亚太唯一,阿里云连续5年位居Gartner®云数据库管理系统报告「领导者」
亚太唯一,阿里云连续5年位居Gartner®云数据库管理系统报告「领导者」
|
6月前
|
人工智能 NoSQL 关系型数据库
阿里云连续五年获评为Gartner®云数据库管理系统魔力象限领导者
阿里云连续五年获评为Gartner®云数据库管理系统魔力象限领导者
|
6月前
|
存储 监控 数据挖掘
消防行业如何借助时序数据库 TDengine 打造高效的数据监控与分析系统
本篇文章来自“2024,我想和 TDengine 谈谈”征文活动的优秀投稿,深入探讨了如何在消防行业中运用 TDengine 进行业务建模。文章重点介绍了如何通过 TDengine 的超级表、标签设计和高效查询功能,有效管理消防监控系统中的时序数据。作者详细阐述了实时监控、报警系统以及历史数据分析在消防行业中的应用,展示了 TDengine 在数据压缩、保留策略和分布式架构下的强大优势。
182 0