Oracle数据到MaxCompute乱码问题详解
簡介:集成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; 】
DUMP
CONVERT
為了避免轉碼正確是因為剛好亂碼的列的真實字符集與操作系統字符集相同而導致顯示正常,選擇了使用 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
這個函數輸出的信息有三個
通過這些信息,我們猜測原來的字符集可能是 GBK 或者 GB18030、GB2312 這幾個字符集的編碼。因為三個漢字,如果是 UTF8 的話他們的編碼大部分都是一個漢字對應三字節。而 GBK字符集對應的編碼是雙字節。
3.查看c0,ee,be,b0,ea,bb 對應的 GBK 字符
GBK 編碼范圍, GBK 編碼表
c0,ee
be,b0
ea,bb
所以,可以認定這個字符編碼屬于 GBK 類。
4.對應漢子的 GBK 類編碼
漢字字符集編碼查詢;中文字符集編碼:GB2312、BIG5、GBK、GB18030、Unicode
李
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 的字符串編碼
網址:Unicode編碼轉換,UTF編碼轉換(UTF-8、UTF-16、UTF-32)
李
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。
字符串函數 - 云原生大數據計算服務 MaxCompute - 阿里云
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
原文鏈接
 本文為阿里云原創內容,未經允許不得轉載。?
總結
以上是生活随笔為你收集整理的Oracle数据到MaxCompute乱码问题详解的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 新能源汽车太猛了,这些卡脖子技术你了解吗
 - 下一篇: 浅谈 Linux 高负载的系统化分析