暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle数据库字符集对GB18030-2022的支持情况

IT那活儿 2024-08-06
1145

点击上方“IT那活儿”公众号--专注于企业全栈运维技术分享,不管IT什么活儿,干就完了!!!


背景介绍

1.1 国标GB18030

GB18030编码采用单字节、双字节、四字节分段编码方案,GB18030向下兼容GBK和GB2312编码。
国家标准GB18030《信息技术汉字编码字符集》是我国继GB2312-1980和GB13000-1993之后最重要的汉字编码标准,是我国计算机系统必须遵循的基础性标准之一。
GB18030有三个版本
  • GB18030-2000是GBK的取代版本,它的主要特点是在GBK基础上增加了CJK统一汉字扩充A的汉字。
  • GB18030-2005的主要特点是在GB18030-2000基础上增加了CJK统一汉字扩充B的汉字。
  • GB18030-2022则主要增加了CJK统一汉字扩充C、D、E、F区的汉字。
GB18030-2000编码标准《信息技术 汉字编码字符集 基本集的扩充》是由信息产业部和国家质量技术监督局在2000年3月17日联合发布的,并且将作为一项国家标准在2001年的1月正式强制执行。GB18030-2000仅规定了常用非汉字符号和27533个汉字(包括部首、部件等)的编码。
GB18030-2005《信息技术 汉字编码字符集》是以汉字为主并包含多种我国少数民族文字的超大型汉字编码字符集,其中收入汉字70000余个。在GB18030-2000的基础上增加了42711个汉字和多种我国少数民族文字的编码(如藏、蒙古、傣、彝、朝鲜、维吾尔文等)。增加的这些内容是推荐性的,原GB18030-2000中的内容是强制性的,市场上销售的产品必须符合。故GB18030-2005为部分强制性标准,自发布之日起代替GB18030-2000。

GB18030-2022《信息技术 汉字编码字符集》在2005版基础上再增加了一万多个汉字,使得汉字总数达到87887个,全面覆盖了《通用规范汉字表》中的汉字。收录的少数民族文字包括:

  • 藏文
  • 滇东北苗文
  • 彝文
  • 傈僳文
  • 朝鲜文
  • 西双版纳新傣文
  • 西双版纳老傣文
  • 维吾尔文
  • 哈萨克文
  • 柯尔克孜文
  • 蒙古文
  • 德宏傣文等

1.2 政策说明

强制性国家标准GB 18030-2022《信息技术 汉字编码字符集》于2023年8月1日起正式实施,其适用范围是具备汉字信息处理及交换功能的软硬件产品。将不再使用伪编码方式替换生僻字,即GB18030-2022涵盖所有的汉字和生僻字,同时该标准也被收录到unicode 11.0标准。

1.3 Unicode编码与CJK对应说明

随着国际编码unicode的不断扩展,支持的汉字数量也在不断增加,上图中是unicode版本与GBK的对应关系,当前的unicode11.0相当于涵盖GB18030-2022中的八万多个字,后面我们进行逐个测试。


Oracle数据库支持说明

GB18030 是中国政府标准,定义了中国软件所需的语言和字符集支持。它是一种符合 ISO 10646/Unicode 的 Unicode 转换格式,并提供涵盖所有 Unicode 代码点的字符库。它最初于 2000 年发布 (GB18030-2000),随后于 2005 年 (GB18030-2005) 和 2022 年 (GB18030-2022) 发布了 2 次更新。GB18030-2022的内容在字符覆盖率方面相当于Unicode Version 11.0。GB18030-2022标准的实施日期为2023年8月1日。
Oracle 数据库通过 AL32UTF8 Unicode 数据库字符集支持 GB18030 字符的存储。还提供客户端专用字符集ZHS32GB18030,使应用程序能够在客户端处理GB18030编码文本的输入/输出,并根据需要进行字符集转换。截至 2023 年 6 月, Oracle完全支持GB18030-2005,并通过AL32UTF8字符集存储GB18030-2005。
Oracle Database 23c 版本中已实现对最新 GB18030-2022 标准的支持。具体来说,Oracle Database 23c 支持 GB18030-2022 标准的实现级别 3,这是 GB18030 可用的最广泛的支持级别。与此同时,还为现有客户提供 GB18030-2022 支持,作为 Oracle Database 19c RU 版本之上的一次性补丁。
Oracle Database 19c 的 GB18030-2022 一次性补丁 (#34994751) 下载。它可以应用于 Oracle 19c RU 版本 19.3 或更高版本。

从ORACLE版本的支持矩阵来看,建议使用19C的长支撑版本,也是当前安装部署的建议版本。


测试环境说明

本次测试主要是对ORACLE的两个字符集ZHS16GBK和AL32UTF8对GB18030国标的支持程度,以及测试ZHS16GBK到AL32UTF8的汉字数据同步情况。

源端数据库
目标端数据库
同步软件
软件版本
ORACLE 19.20.0.0.0
ORACLE 11.2.0.4.0
Version 21.3.0.0.0 OGGCORE_21.3.0.0.0_PLATFORMS_210728.1047_FBO
字符集
AL32UTF8
ZHS16GBK
N/A
国家字符集
AL16UTF16
AL16UTF16
N/A
架构
单机
单机
单机
操作系统
CentOS Linux release 7.4.1708 (Core)
CentOS Linux release 7.3.1611 (Core)

CentOS Linux release 7.4.1708 (Core)

CentOS Linux release 7.3.1611 (Core)


3.1 源数据库(AL32UTF8)

3.1.1 版本及补丁信息

1)数据库RU,MRP补丁集
oracle@host_1476:[/oracle/ogg21] opatch lsinv|grep "Patch description"
Patch description: "CN NEED SUPPORT GB18030-2022 IN 19C"
Patch description: "MERGE ON DATABASE RU 19.20.0.0.0 OF 35525143 35784008"
Patch description: "
MERGE ON DATABASE RU 19.20.0.0.0 OF 35585502 35754528"
Patch description: "
MERGE ON DATABASE RU 19.20.0.0.0 OF 35617844 35623675"
Patch description: "
THOUSANDS OF NEW OLINT WARNINGS INTRODUCED BY TRANSACTION SKSAMUDR_BUG-35360571"
Patch description: "
Fix for bug 35635081"
Patch description: "
Fix for bug 35598911"
Patch description: "
TRACKING BUG FOR SQLCL CHANGES IN SQLDEVELOPER 21.4.10"
Patch description: "
EXACS - ACFS CORRUPTION ISSUE"
Patch description: "
DOMAIN NAME IS MISSING FOR SERVICE POST GI PATCH TO 19.18"
Patch description: "
MERGE FAILS WITH ORA-00600  [13013] IN 19.17 EVEN WITH FIX 34884598"
Patch description: "
STABLE E3POD ORA-600 [KRCCSIO_1] CTWR CRASH"
Patch description: "
DATABASE TERMINATED WITH ORA-600 [KCBB_PREPARE_4], [3], [], [] ON UNIQUE INDEX ON A PARTITIONED TABLE"
Patch description: "
Database Release Update : 19.20.0.0.230718 (35320081)"
Patch description: "
OCW RELEASE UPDATE 19.3.0.0.0 (29585399)"

2)补丁34994751,支持GB18030-2022
$opatch lspatches |grep 34994751
34994751;CN NEED SUPPORT GB18030-2022 IN 19C

3.1.2 数据库字符集

PARAMETER VALUE
------------------------------ ------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_CHARACTERSET AL32UTF8
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE

数据库字符集AL32UTF8 ,国家字符集AL16UTF16,官方介绍19C在打上34994751补丁后,支持GB18030-2022国标,支持8万多汉字。

3.2 目标数据库(ZHS16GBK)

3.2.1 版本及补丁信息

--------------------------------------------------------------------------------
Installed Top-level Products (1):
Oracle Database 11g 11.2.0.4.0
There are 1 products installed in this Oracle Home.
There are no Interim patches installed in this Oracle Home.
--------------------------------------------------------------------------------

3.2.2 数据库字符集

数据库字符集ZHS16GBK ,国家字符集AL16UTF16,官方介绍ZHS16GBK即GBK,支持2万多汉字。


汉字兼容测试

本次测试主要是测试三个方面:

  • 一是GBK集汉字同步测试,数据在GBK编码范围内(0x8140-0xFEFE),数据从AL32UTF8到ZHS16GBK的同步情况;
  • 二是扩展集汉字同步测试,从CJK扩A-G中汉字的同步测试;
  • 三是GBK集和扩展集的混合的同步测试;
环境初始化。
数据表:TEST.HANZI。
字段信息:ID 唯一值、VCOL 字符字段1、NCOL 字符字段2。
备注:为测试VARCHAR2到NVARCHAR2的同步,NCOL字段源端是VARCHAR2类型,目标端是NVARCHAR2类型。
CREATE TABLE TEST.HANZI
   ( ID NUMBER PRIMARY KEY ,
       VCOL VARCHAR2(10),
       NCOL VARCHAR2(10)
  )
TABLESPACE TESTTBS ;

CREATE TABLE TEST.HANZI
   ( ID NUMBER PRIMARY KEY ,
       VCOL VARCHAR2(10),
       NCOL NVARCHAR2(10)
  )
TABLESPACE TESTTBS ;

配置OGG的同步表TEST.HANZI(OGG配置过程省略)
EXTRACT e1
SETENV (NLS_LANG="AMERICAN_AMERICA.AL32UTF8")
SETENV (ORACLE_HOME = "/oracle/app/oracle/product/19.0.0/dbhome_1")
SETENV (ORACLE_SID = "dbname")
DISCARDFILE ./dirrpt/e1.dsc, APPEND, MEGABYTES 1024
EXTTRAIL ./dirdat/e1
GETTRUNCATES
NOCOMPRESSDELETES FETCHMISSINGCOLUMNS
NOCOMPRESSDELETES
NOCOMPRESSUPDATES
USERID gguser@11.11.11.11:1521/dbname, PASSWORD Dbname
TABLE TEST.HANZI;

EXTRACT p1
PASSTHRU
RMTHOST 11.11.11.12, MGRPORT 7809, compress
RMTTRAIL ./dirdat/r1
TABLE test.HANZI;

REPLICAT r1
SETENV (NLS_LANG="AMERICAN_AMERICA.AL32UTF8")
SETENV (ORACLE_HOME = "/ora/oracle/product/11.2.0/db_1")
SETENV (ORACLE_SID = "dbname")
USERID gguser@11.11.11.12:1521/dbname,PASSWORD Dbname
discardfile ./dirrpt/r1.dsc,purge
ASSUMETARGETDEFS
--SOURCECHARSET PASSTHRU
MAP test.hanzi, TARGET test.hanzi;

4.1 GBK集汉字测试

测试汉字: “中国人”。
  • 源端(客户端设置UTF8字符集)
SQL> insert into test.hanzi values(1,'中国人','中国人');
1 row created.
SQL>
 commit;
Commit complete.
SQL>
 SELECT * FROM test.hanzi;
        ID VCOL NCOL
---------- ---------- ----------
         1 中国人 中国人

  • 目标端(客户端设置GB18030字符集)
SQL> SELECT * FROM test.hanzi;

        ID VCOL NCOL
---------- ---------- --------------------
         1 中国人 中国人

从上面输出中文看,直接输出是没有问题的,从编码级别看一下两端的输出
  • 源端:
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi;

        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

         1
Typ=1 Len=9 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba
Typ=1 Len=9 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba

  • 目标端:
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi;

        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

         1
Typ=1 Len=6 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c8,cb
Typ=1 Len=6 CharacterSet=AL16UTF16: 4e,2d,56,fd,4e,ba

数据库里dump的结果:
  • ZHS16GBK: d6,d0,b9,fa,c8,cb 与 GBK D6D0 B9FA C8CB 相同。
  • AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba 与UTF-8 E4B8AD E59BBD E4BABA相同。
  • AL16UTF16: 4e,2d,56,fd,4e,ba 与UTF-16BE  4E2D 56FD 4EBA 相同。
说明数据库中汉字的编码通过OGG同步后是可以在两个字符集之间正常转换和显示。

4.2 扩展集汉字测试

扩展的测试汉字:䶮𠇔
𠇔

从扩展字符集里选择4个汉字进行测试。由于当前测试计算机不支持gb18030-2022字符集,故打出的汉字现象成”□”,入库的时候只能使用编码方式进行入库。

4.2.1 测试varchar2类型

  • 源端:
SQL> insert into test.hanzi values (2,utl_raw.cast_to_varchar2('E4B6AE'),'v2') ;
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM test.hanzi;
        ID VCOL NCOL
---------- ---------- ----------
         1 中国人 中国人
         2 䶮 v2

SQL>
 select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=2;
        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
         2
Typ=1 Len=3 CharacterSet=AL32UTF8: e4,b6,ae
Typ=1 Len=2 CharacterSet=AL32UTF8: 76,32

源端插入后,同步数据,OGG报错。
2023-11-13 11:25:17 ERROR OGG-03533 Conversion from character set UTF-8 of source column VCOL to character set zhs16gbk of target column VCOL failed b
ecause the source column contains a character 'e4 b6 ae' at offset 0 that is not available in the target character set.

报错说明该汉字在目标端ZHS16GBK中无法识别和转换,可以添加参数SOURCECHARSET PASSTHRU,强行同步,同步后看下数据。
2023-11-13 11:27:38  ERROR OGG-02552  The SOURCECHARSET PASSTHRU parameter does not support CHAR/VARCHAR/CLOB to/from NCHAR/NVARCHAR/NCLOB mappings.
添加参数后,由于目标端表中存在nvarchar2类型,所以无法同步,为暂时测试需要先把nvarchar2类型修改为varchar2,数据同步后,查询目标端的表。
SQL> SELECT * FROM test.hanzi;
SP2-0784: Invalid or incomplete character beginning 0xAE returned
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi;
        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
         2
Typ=1 Len=3 CharacterSet=ZHS16GBK: e4,b6,ae
Typ=1 Len=2 CharacterSet=ZHS16GBK: 76,32

我们看编码ZHS16GBK: e4,b6,ae ,被透明同步过来,很明显这是错误的,因为目标端是GBK字符集,无法识别此编码。
所以通过上面测试说明,ZHS16GBK无法识别到扩展A的汉字,即使强制同步,数据也无法被正确识别。

4.2.2 测试nvarchar2类型

上面章节测试varchar2类型是无法对扩展字符集进行同步,这里测试nvarchar2类型,即源端varchar2类型对应目标端nvarchar2类型。
1)GBK集汉字测试
首先OGG取消参数设置SOURCECHARSET PASSTHRU:
2023-11-13 14:45:44  ERROR OGG-02552  The SOURCECHARSET PASSTHRU parameter does not support CHAR/VARCHAR/CLOB to/from NCHAR/NVARCHAR/NCLOB mappings.
  • 源端
SQL> insert into test.hanzi values (12,'nv2','中国人') ;
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM test.hanzi WHERE id=12;

        ID VCOL NCOL
---------- ---------- ----------
        12 nv2 中国人

SQL>
 select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=12;


        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
        12
Typ=1 Len=3 CharacterSet=AL32UTF8: 6e,76,32
Typ=1 Len=9 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba

  • 目标端
SQL> SELECT * FROM test.hanzi WHERE id=12;
        ID VCOL NCOL
---------- ---------- --------------------
        12 nv2 中国人
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=12;
        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
        12
Typ=1 Len=3 CharacterSet=ZHS16GBK: 6e,76,32
Typ=1 Len=6 CharacterSet=AL16UTF16: 4e,2d,56,fd,4e,ba

数据库里dump的结果:
  • 源端的AL32UTF8: e4,b8,ad,e5,9b,bd,e4,ba,ba 对应GBK编码;
  • 目标端的AL16UTF16: 4e,2d,56,fd,4e,ba对应UTF-16BE编码,说明可以正常进行编码转换。
说明数据库中汉字的编码通过OGG同步后是可以在两个字符集之间正常转换和显示。
2)扩展集汉字测试
  • 源端
SQL> SELECT * FROM test.hanzi WHERE id=13;
        ID VCOL NCOL
---------- ---------- ----------
        13 nv2 䶮中
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=13;

        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
        13
Typ=1 Len=3 CharacterSet=AL32UTF8: 6e,76,32
Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b6,ae,e4,b8,ad

  • 目标端
[oracle@sjtdb ~]$ export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
SQL> SQL> SELECT * FROM test.hanzi WHERE id=13;
        ID VCOL
---------- ------------------------------
NCOL
----------------------------------------

        13 nv2
䶮中

SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=13;

        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

        13
Typ=1 Len=3 CharacterSet=ZHS16GBK: 6e,76,32
Typ=1 Len=4 CharacterSet=AL16UTF16: 4d,ae,4e,2d

从上面看到源端AL32UTF8: e4,b6,ae,e4,b8,ad和目标端AL16UTF16: 4d,ae,4e,2d,可以成功转换,也可以正常显示数据。
说明数据库中汉字的编码通过OGG同步后是可以在两个字符集之间正常转换和显示,就目前测试的四个字都可以在目标端正常转换,官方回复是AL16TUF16字符集有不识别的汉字。

4.3 混合GBK集和扩展集测试

  • 源端:
SQL> insert into test.hanzi values (3,'䶮中','v2') ;
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM test.hanzi WHERE id=3;
        ID VCOL NCOL
---------- ---------- ----------
         3 䶮中 v2

SQL>
 select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=3;
        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
         3
Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b6,ae,e4,b8,ad
Typ=1 Len=2 CharacterSet=AL32UTF8: 76,32
SQL> insert into test.hanzi values (4,utl_raw.cast_to_varchar2('E4B6AE')||'人','v2') ;
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM test.hanzi WHERE id=4;
        ID VCOL NCOL
---------- ---------- ----------
         4 䶮人 v2
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=4;
        ID
----------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
         4
Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b6,ae,e4,ba,ba
Typ=1 Len=2 CharacterSet=AL32UTF8: 76,32

  • 查询目标端的表:
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi ;
        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

         2
Typ=1 Len=3 CharacterSet=ZHS16GBK: e4,b6,ae
Typ=1 Len=2 CharacterSet=ZHS16GBK: 76,32
         3
Typ=1 Len=6 CharacterSet=ZHS16GBK: e4,b6,ae,e4,b8,ad
Typ=1 Len=2 CharacterSet=ZHS16GBK: 76,32
        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

         4
Typ=1 Len=6 CharacterSet=ZHS16GBK: e4,b6,ae,e4,ba,ba
Typ=1 Len=2 CharacterSet=ZHS16GBK: 76,32

客户端是UTF-8查询数据:# 本身就违背数据库字符集,只作测试。
SQL> SELECT * FROM test.hanzi WHERE id=4;
        ID VCOL NCOL
---------- ---------- ----------
         4 䶮人 v2
SQL> SELECT * FROM test.hanzi WHERE id=3;
        ID VCOL NCOL
---------- ---------- ----------
         3 䶮中 v2
SQL> SELECT * FROM test.hanzi WHERE id=2;
SP2-0784: Invalid or incomplete character beginning 0xAE returned

客户端是GB18030查询数据:
SQL> SELECT * FROM test.hanzi WHERE id=2;
SP2-0784: Invalid or incomplete character beginning 0xAE returned
SQL> SELECT * FROM test.hanzi WHERE id=3;
        ID VCOL NCOL
---------- ---------- ----------
         3 涠腑 v2
SQL> SELECT * FROM test.hanzi WHERE id=4;
        ID VCOL NCOL
---------- ---------- ----------
         4 涠汉 v2

我们看源端和目标端的编码CharacterSet=AL32UTF8: e4,b6,ae,e4,ba,ba 和CharacterSet=ZHS16GBK: e4,b6,ae,e4,ba,ba是一样的,很明显这是错误的,因为目标端是GBK字符集,按照GBK的编码无法解码,故出来的汉字是与源端不同,即未正确识别。
所以通过上面测试说明,ZHS16GBK无法识别到扩展A的汉字,即使强制同步,数据也无法被正确识别。

4.4 扩展F集汉字测试

源端插入汉字,因为本地计算机不支持扩F字,导致出现□。
SQL> insert into test.hanzi values (16,'kE',utl_raw.cast_to_varchar2('F0AEA7B5')||'中') ;
1 row created.
SQL> SELECT * FROM test.hanzi WHERE id=16;
        ID VCOL NCOL
---------- ---------- ----------
        14 kE 𮧵中
SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=14;
        ID
----------
COL1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        16
Typ=1 Len=2 CharacterSet=AL32UTF8: 6b,45
Typ=1 Len=7 CharacterSet=AL32UTF8: f0,ae,a7,b5,e4,b8,ad

目标端数据同步,查看DUMP信息,输出UTF16编码:
SQL> SELECT * FROM test.hanzi WHERE id=16;
        ID VCOL
---------- ------------------------------
NCOL
----------------------------------------

        16 kE
𮧵中

SQL> select id,dump(vcol,1016) col1,dump(ncol,1016) col2 from test.hanzi WHERE id=16;
        ID
----------

COL1
--------------------------------------------------------------------------------

COL2
--------------------------------------------------------------------------------

        16
Typ=1 Len=2 CharacterSet=ZHS16GBK: 6b,45
Typ=1 Len=6 CharacterSet=AL16UTF16: d8,7a,dd,f5,4e,2d

说明数据库中扩F汉字的编码通过OGG同步后是可以在两个字符集之间正常转换,显示跟客户端支持字符集有关系。

附 录:

1)AL32UTF8是不是ZHS16GBK的超集

是的。
ZHS16GBK汉字编码的区域是0x8140-0xFEFE,这个编码范围也就是GBK的编码范围,AL32UTF8在19C不打补丁之前是兼容到GB18030-2005,故从范围来看,AL32UTF8是ZHS16GBK的超集。
可以通过自带的图形化工具查看$ORACLE_HOME/nls/lbuilder/lbuilder。

2)AL32UTF8和AL16UTF16是不是具备相同UNICODE范围

是的。
这里的理解是说,两个字符集是不是属于同一套unicode的编码, 在al32utf8中的所有编码都在al16utf16中可以正常转换。也就是说n-types可以完全可以作为al32utf8的目标端,不会出现空码问题。

3)使用N-types(AL16UTF16)的优劣势

如上面说到如果n-types都可以包含unicode,是不是可以替代varchar2/char等类型。以下是官方列出的n-types的优劣势。
  • n-types优势,总结就是汉字占比高会节省空间
    a) one possible (but rather theoretical) advantage is storage (disk space) for NCHAR/NVARCHAR2.
    b) other possible advantage is extending the limits of CHAR semantics.
  • n-types劣势
    * You might have some problems with older clients if using AL16UTF16 see point 6) b) in this note
    * Be sure that you use (AL32)UTF8 as NLS_CHARACTERSET , otherwise you will run into point 13 of this note.
    * Do not expect a higher *performance* by using NCHAR, NVARCHAR2 and NCLOB  instead of CHAR, VARCHAR2 and CLOB with an AL32UTF8 NLS_CHARACTERSET , it might be a little bit faster on some systems, but that has more to do with I/O then with the database kernel and the difference will not be noticable in the overall picture.
    * Forms 6i/9i does not support NCHAR NVARCHAR2. This is documented in the 6i Forms online help.
    * If you use N-types, DO use the (N'...') syntax when coding it so that Literals are denoted as being in the national character set by prepending letter 'N'.
    劣势,总结是:1.老的客户端不识别,2.性能有影响,3.插入数据需要’ N’形式,对查询没有影响,4.不允许跟zhs16gbk的varchar在一起,会导致客户端字符集无法正确解析汉字。
最后官方回复n-types也会有不涵盖的汉字,建议目标端使用al32utf8。

END


本文作者:孙其成(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论