共计 5315 个字符,预计需要花费 14 分钟才能阅读完成。
简介:集成 Oracle 数据到 MaxCompute,乱码问题剖析;为什么,在 oracle 数据不乱码,集成到 MaxCompute 就乱码了? 问题在哪里?
1.1 乱码景象
DataWorks 的数据离线集成 (DataX) 集成 Oracle 数据到 MaxCompute 的数据有乱码,然而看源库不是乱码,这是什么起因?
景象:【Oracle;工具:plsql-dev】
【MaxCompute;工具:DataWorks】
select OP_USER from test.mdtsb where
uuid=’161A45E75BC88040E053441074848040′;
1.2 问题剖析
应用两个 oracle 函数:
【DUMP; CONVERT;】
http://docs.oracle.com/databa…
http://docs.oracle.com/databa…
为了防止转码正确是因为刚好乱码的列的实在字符集与操作系统字符集雷同而导致显示失常,抉择了应用 linux 环境,客户端字符集设置为 UTF8,应用 SQLplus 进行查问剖析问题。
1.客户端环境:
SQL> select userenv(‘language’) from dual;
USERENV(‘LANGUAGE’)
SIMPLIFIED CHINESE_CHINA.AL32UTF8
2.应用 dump 函数把文本对应的编码输入进去:
SQL> select dump(OP_USER,1016) from test.mdtsb where
uuid=’161A45E75BC88040E053441074848040′ ;
DUMP(OP_USER,1016)
Typ=1 Len=6CharacterSet=AL32UTF8: c0,ee,be,b0,ea,bb
这个函数输入的信息有三个
- 长度是 6 字节
- 字符集是 AL32UTF8
- 字符编码是 c0,ee,be,b0,ea,bb
通过这些信息,咱们猜想原来的字符集可能是 GBK 或者 GB18030、GB2312 这几个字符集的编码。因为三个汉字,如果是 UTF8 的话他们的编码大部分都是一个汉字对应三字节。而 GBK 字符集对应的编码是双字节。
3.查看 c0,ee,be,b0,ea,bb 对应的 GBK 字符
http://www.qqxiuzi.cn/zh/hanz…
c0,ee
be,b0
ea,bb
所以,能够认定这个字符编码属于 GBK 类。
4.对应汉子的 GBK 类编码
http://www.qqxiuzi.cn/bianma/…
李
GB2312 编码:C0EE
BIG5 编码:A7F5
GBK 编码:C0EE
GB18030 编码:C0EE
Unicode 编码:674E
景
GB2312 编码:BEB0
BIG5 编码:B4BA
GBK 编码:BEB0
GB18030 编码:BEB0
Unicode 编码:666F
昊
GB2312 编码:EABB
BIG5 编码:A9FE
GBK 编码:EABB
GB18030 编码:EABB
Unicode 编码:660A
能够看到,这三个汉字可能的编码是:GB2312、GB18030、GBK。
5.应用 convert 函数转换字符串编码为 AL32UTF8
SQL> select convert(OP_USER,’AL32UTF8′,’ZHS16GBK’) from test.mdtsb where
uuid=’161A45E75BC88040E053441074848040′ ;
CONVERT(OP_USER,’ AL32UTF8′,’ZHS16GBK’)
李景昊
这个后果验证了咱们的猜想,这个字符集应该是 GBK 类的字符集,然而因为 GBK 和 GB18030、GB2312 并不是齐全父子集关系,所以,这个只能是其中的一种。只不过 GBK 字符集从以后角度来看,更为罕用。
SQL> select convert(OP_USER,’AL32UTF8′,’ZHS16GBK’) from test.mdtsb where
uuid=’161A45E75BC88040E053441074848040′ ;
CONVERT(OP_USER,’ AL32UTF8′,’ZHS16CGB231280′)
李景昊
SQL> select convert(OP_USER,’AL32UTF8′,’ZHS16GBK’) from test.mdtsb where
uuid=’161A45E75BC88040E053441074848040′ ;
CONVERT(OP_USER,’ AL32UTF8′,’ZHS32GB18030′)
李景昊
6.查问这三个汉字对应的 UTF8 的字符串编码
网址:http://www.qqxiuzi.cn/bianma/…
李
Unicode 编码:0000674E
UTF8 编码:E69D8E
UTF16 编码:FEFF674E
UTF32 编码:0000FEFF0000674E
景
Unicode 编码:0000666F
UTF8 编码:E699AF
UTF16 编码:FEFF666F
UTF32 编码:0000FEFF0000666F
昊
Unicode 编码:0000660A
UTF8 编码:E6988A
UTF16 编码:FEFF660A
UTF32 编码:0000FEFF0000660A
所以,如果原来字符串编码是 UTF8,实践上咱们通过 dump 函数获取的字符串编码应该为:e6,9d,8e,e6,99,af,e6,98,8a
1.3 问题解决
通过 convert 函数转换:
SQL> select dump(convert(OP_USER,’AL32UTF8′,’ZHS16GBK’),1016) from test.mdtsb
where uuid=’161A45E75BC88040E053441074848040′ ;
DUMP(CONVERT(OP_USER,’ AL32UTF8′,’ZHS16GBK’),1016)
Typ=1 Len=9CharacterSet=AL32UTF8: e6,9d,8e,e6,99,af,e6,98,8a
这个后果验证了咱们之前的查问后果,UTF8 字符集显示的编码应该是:
e6,9d,8e,e6,99,af,e6,98,8a。
论断:
Oracle 数据库存储的该列的理论编码是 GBK 类的字符集,因为与客户端环境的字符编码雷同,所以,刚好能显示进去。然而因为 Oracle 存储的字符集设置为 UTF8,实际上存储的字符集应该是 UTF8。所以导致标注的编码和理论的编码不统一 - 乱码。
应答:
在数据同步工作的对应的列上通过测试字符集获取到的实在字符集,应用 convert 函数(convert(OP_USER,’AL32UTF8′,’ZHS16GBK’))进行转换,转换到 ODPS 后的数据就不会再是乱码。
例如:SELECT convert(KEY1,’ZHS16GBK’,’UTF8′) FROM MATDOC;
【MaxCompute;工具:DataWorks】
select OP_USER from MaxCompute.MDTSB where uuid=’161A45E75BC88040E053441074848040′;
1.4 指标端识别方法
其实在 MaxCompute 也有相干的函数能够对字符编码进行剖析和转换,只是咱们在 MaxCompute 只能存储一种字符集“UTF-8”,所以,最好是在源端或者在传输过程中转换编码为 UTF-8。上面两个函数是 MaxCompute 的字符编码相干函数。
· ENCODE
命令格局
binary encode(string <str>, string)
命令阐明
将 str 依照 charset 格局进行编码。
参数阐明
str:必填。STRING 类型。待从新编码的字符串。
charset:必填。STRING 类型。编码格局。取值范畴为:UTF-8、UTF-16、UTF-16LE、UTF-16BE、ISO-8859-1、US-ASCII。
返回值阐明
返回 BINARY 类型。任一输出参数为 NULL 时,返回后果为 NULL。
示例
示例 1:将字符串 abc 依照 UTF- 8 格局编码。命令示例如下。
select encode(“abc”, “UTF-8”);
– 返回 abc。
· IS_ENCODING
命令格局
boolean is_encoding(string <str>, string , string)
命令阐明
判断输出的字符串 str 是否能够从指定的一个字符集 from_encoding 转为另一个字符集 to_encoding。也能够用于判断输出是否为乱码,通常您能够将 from_encoding 设为 UTF-8,to_encoding 设为 GBK。
参数阐明
str:必填。STRING 类型。空字符串能够被认为属于任何字符集。
from_encoding、to_encoding:必填。STRING 类型,源及指标字符集。
返回值阐明
返回 BOOLEAN 类型。如果 str 可能胜利转换,则返回 True,否则返回 False。如果任一输出参数为 NULL,则返回 NULL。
示例
示例 1:判断字符测试或測試是否能够从 utf- 8 字符集转为 gbk 字符集。命令示例如下。
select is_encoding(‘ 测试 ’, ‘utf-8’, ‘gbk’);
– 返回 true。
select is_encoding(‘ 測試 ’, ‘utf-8’, ‘gbk’);
– 返回 true。
https://help.aliyun.com/docum…
1.5 附录
Convert 函数
Purpose
CONVERT converts a character string from one character set to another. The datatype of the returned value is VARCHAR2.
- The char argument is the value to be converted. It can be
any of the datatypes CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB, or NCLOB.
- The dest_char_set argument is the name of the character set to which char is converted.
- The source_char_set argument is the name of the character set in which char is stored in the database. The default value is the database character set.
Both the destination and source character set arguments can be either literals or columns containing the name of the character set.
For complete correspondence in character conversion, it is essential that the destination character set contains a representation of all the characters defined in the source character set. Where a character does not exist in the destination character set, a replacement character appears. Replacement characters can be defined as part of a character set definition.
Examples
The following example illustrates character set conversion by converting a Latin-1 string to ASCII. The result is the same as importing the same string from a WE8ISO8859P1 database to a US7ASCII database.
SELECT CONVERT(‘Ä Ê Í Ó Ø A B C D E ‘, ‘US7ASCII’, ‘WE8ISO8859P1’)
FROM DUAL;
CONVERT(‘ÄÊÍÓØABCDE’
A E I ? ? A B C D E ?
【’US7ASCII’ 是以后 oracle 数据库的字符集,’WE8ISO8859P1’ 是被转换后的字符集】
Common character sets include:
· US7ASCII: US 7-bit ASCII character set
· WE8DEC: West European 8-bit character set
· F7DEC: DEC French 7-bit character set
· WE8EBCDIC500: IBM West European EBCDIC Code Page 500
· WE8ISO8859P1: ISO 8859-1 West European 8-bit character set
· UTF8: Unicode 4.0 UTF-8 Universal character set, CESU-8 compliant
· AL32UTF8: Unicode 4.0 UTF-8 Universal character set
原文链接
本文为阿里云原创内容,未经容许不得转载。