GaussDB(DWS) GDS导入fixed格式数据文件字符转换问题

举报
i云上小白 发表于 2023/09/28 14:38:26 2023/09/28
【摘要】  在GaussDB(DWS)数据库中,支持的字符编码有GBK、UTF8、Latin1和SQL_ASCII,其中Latin1和SQL_ASCII属于单字节编码,可以存储任何编码规则字符。GBK是中文字符集,使用2个字节编码一个中文字符,而在UTF8中一般使用3个字节编码一个中文字符。对于fixed格式的数据文件,如果里面包含中文,当字符编码从GBK转为UTF8时,字符存储长度增加,会导致根据长...

 

GaussDB(DWS)数据库中,支持的字符编码有GBKUTF8Latin1SQL_ASCII,其中Latin1SQL_ASCII属于单字节编码,可以存储任何编码规则字符。GBK是中文字符集,使用2个字节编码一个中文字符,而在UTF8中一般使用3个字节编码一个中文字符。对于fixed格式的数据文件,如果里面包含中文,当字符编码从GBK转为UTF8时,字符存储长度增加,会导致根据长度确定字段的位置发生错误,出现数据混乱。

我们使用GDS进行测试,数据库版本为8.0.0.8,数据文件格式为fixed,字符编码为GBKGDS外表定义如下,将其导入GBK编码的数据库后,中文字段可正常显示,如下图:

CREATE FOREIGN TABLE f_imp_tb95 (
c1 character varying(5) position(0,5),
c2 character varying(5) position(5,5),
c3 character varying(5) position(10,5),
c4 character varying(1) position(15,1),
c5 character varying(40) position(16,40),
c6 character varying(1) position(56,1),
c7 character varying(1) position(57,1),
c8 character varying(5) position(58,5),
c9 character varying(3) position(63,3),
c10 character varying(7) position(66,7),
c11 character varying(60) position(73,60),
c12 character varying(5) position(133,5),
c13 character varying(50) position(138,50)) 
SERVER gsmpp_server OPTIONS (location 'gsfs://192.168.10.4:5000/*',format 'FIXED' ,encoding 'GBK' ,mode 'Normal' ,compatible_illegal_chars 'true') with f_imp_err_tb95;

1.png

由于Latin1字符编码可以存储任意编码规则的字符,如果将外表字符编码设置为encoding ‘Latin1’,客户端和服务端编码一致,则字符可在不转码的情况下存储到Latin1编码的库中,数据仍然可以正常显示,如下图:

2.png

上述两种情况由于GBK编码的字符均未发生转码,因此根据定长格式可以正常识别到字符位置。倘若将该数据文件导入UTF8编码的数据库中(外表定义:encoding 'GBK'),此时由于存在转码,数据显示混乱。如下图:

3.png

造成上面结果混乱的原因为,字符从GBK到UTF8转码时,数据库先对字符进行了转码操作,然后根据fixed格式定义的字段长度进行截取,由于中文字符由GBK转为UTF8后字段长度增加,导致取值错乱。针对这种情况,8.0.0.3补丁对此进行了优化,对于GDS导入fixed格式文件的场景,当外表设置了conflict_delimiter参数(该参数一般要配合compatible_illegal_chars参数使用)时,内核先不对数据进行转码,而是根据fixed的position参数先识别出每一个字段后再对每一个字段进行GBK->UTF8转码。

根据上述说明,在外表定义中增加参数compatible_illegal_chars 'true',conflict_delimiter 'true',然后将该数据文件导入UTF8编码的数据库中,数据显示正常,如下图:3.png由于中文字段c5c11c13转码后长度增加,因此在外表定义中需要将这3个字段的数据类型从varchar2(n)改为varchar2或者text,这样可以保证中文字符转码后能够正常存储。

GaussDB(DWS) 8.1.3的版本中,该功能已经得到了进一步增强,外表定义中无需再设置参数conflict_delimiter,直接将中文字段类型改为varchar2或者text,数据导入UTF8编码的数据库后,即可正常显示,如下图:

4.png

 

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。