1、前言
当我们在DM7中处理汉字的时候,经常会用到varchar的数据类型。但是,根据数据库初始化时的参数不同,varchar中能存储的汉字的个数也不尽相同。那么在每种情况下,字符的存储有什么区别呢?本文就将带大家一探究竟。
2、参数简介
在使用DMINIT初始化数据库的时候,我们有以下这两个跟字符集有关的参数,UNICODE_FLAG和LENGTH_IN_CHAR。
UNICODE_FALG:此参数表示了数据库中所有数据的字符集,包括数据字典的字符集。需要注意的是,数据库一旦初始化完成,字符集就将无法修改。我们可以使用select unicode来查询当前数据库的字符集种类,0代表gb18030,1代表UTF-8。
LENGTH_IN_CHAR:此参数决定了,数据库中的VARCHAR类型对象的长度是否以字符为单位。取值为1则设置为以字符为单位,将存储长度值按照理论字符长度进行放大。取值为0则所有 VARCHAR 类型对象的长度以字节为单位。
同样,如果我们采用DBCA助手来创建数据库,也可以在初始化参数那一步来修改这两个参数的值。
3、测试
根据Unicode和length_in_char的取值不同(0或1),我们总共初始化四个不同的数据库,针对不同的情况进行测试。
本文演示环境: DM Database Server x64V7.1.6.48-Build(2018.03.01-89507)ENT
3.1、UNICODE_FLAG=0,LENGTH_IN_CHAR=0
根这种情况是初始化数据库时的默认配置,即字符集为gb18030,varchar长度以字节为单位。相关测试如下
我们知道,gb18030下一个汉字或者全角字符一般需要占用两个字节。所以varchar(3)型可以插入一个汉字加上一个半角字符,但是无法插入两个汉字。
3.2、UNICODE_FLAG=1,LENGTH_IN_CHAR=0
字符集为utf-8,varchar长度以字节为单位,相关测试如下:
Utf-8的情况下,一个汉字一般需要占据三个字节,所以varchar(3)只能插入一个汉字。
3.3、UNICODE_FLAG=0,LENGTH_IN_CHAR=1
字符集为utf-8,varchar长度以字符为单位,测试如下
我们知道在length_in_char=1的情况下,varchar的实际可存储字节数会按一定比例放大。所以在使用gb18030的时候,varchar(3)实际可以存储3个汉字,也就是3*2=6个字节的数据。
3.4、UNICODE_FLAG=1,LENGTH_IN_CHAR=1
字符集为utf-8,varchar长度以字符为单位
这里我们会发现一个奇怪的情况,明明设置是varchar(3),为什么可以插入4个汉字呢。这是因为在DM7中数据库实际存储数据是以字节为单位。在lengtg_in_char=1且字符集为utf-8的时候,VARCHAR类型对象的实际存放的最大长度是VARCHAR类型定义的长度*4字节。
也就是说,这里一个varchar(3)的结构可以存放的数据为3*4=12个字节。然而事实上UTF-8中的一个汉字一般只用占用3个字节,所以这里我们可以插入12/3=4个汉字。
4、总结
当LENGTH_IN_CHAR=0的情况下,varchar()的长度是以字节数为单位。这时我们只需要考虑汉字和全角字符所占用字节数,其中gb18030的一个汉字是两个字节,utf-8的一个汉字一般是三个字节。如果插入数据的总字节数大于varchar定义的长度,则会插入失败。
当LENGTH_IN_CHAR=1的情况下,varchar()所能存储的字节数将会按照一定比例扩展。字符集为gb18030时varchar的字节数等于定义长度*2,字符集为utf-8时varchar的字节数为定义长度*4。
上海腾科教育科技有限公司聚焦ICT人才培养和教育服务、培养数字化时代的新型ICT人才、促进良性的ICT人才生态发展,提供面授教育、在线教育、IT人才培养与就业、高校专业共建与实验室建设、企业人才定制培养,以及教育科技领域内的技术开发、咨询、服务以及解决方案,专注高校ICT课程课件研发、基于华为公有云的云实验实训平台建设,致力于ICT技术在高等院校的引进、开发和推广,是一家全国性的专业ICT行业技术认证服务公司。
腾科教育是华为授权的培训合作伙伴,专业提供华为ICT技术架构认证、平台与服务认证、行业服务认证等华为职业认证服务,连续多年荣获华为年度最佳合作伙伴贡献奖、华为优秀战略合作伙伴、上海HCIE精英俱乐部伙伴,连续多年举办腾科技术嘉年华华为专场,并协办华为ICT大赛、华为生态伙伴精英赛伙伴赛分赛场、华为人才双选会上海场等活动和赛事,提供面向华为生态合作伙伴和ICT学员的人才供需双选平台及ICT学员就业通道,培养ICT行业所需创新型、融合型人才。