Oracle字符集转换(九):6.如何转换用户实现的字符集(二)
上一篇文章 (Oracle字符集转换(八):六、如何转换用户实现的字符集(一)),我们来看看用户实现的字符集转换方法。您可以查看如何使用 DB Link、CTAS 和 UTL_RAW 包将 KO16MSWIN949、US7ASCII 转换为 AL32UTF8。
6.2.3.方法 3) 数据库链接 & CTAS & UTL_RAW
这是通过DB Link导入数据时转换字符集的方法。
在一台服务器上配置三个数据库实例并运行三个测试。
- 从 ORAMSWIN949 导入 ORAUS7 数据
- 从 ORAUTF 导入 ORAMSWIN949 数据
- 从 ORAUTF 导入 ORAUS7 数据
可以按如下方式检查 ORAUS7 中保存的韩文数据。
C:\Users\ymlee>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII C:\Users\ymlee>sqlplus leg/leg@oraus7 SQL*Plus: Release 11.2.0.1.0 Production on Sun Jul 17 22:34:26 2022 Copyright (c) 1982, 2010, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> set pagesize 100 SQL> set linesize 200 SQL> select use_mon, line_num, sub_sta_id, sub_sta_nm, ride_pasgr_num, alight_pasgr_num, work_dt 2 from sub_mon_stat 3 where rownum <= 10 4 ; USE_MON LINE_NUM SUB_ SUB_STA_NM RIDE_PASGR_NUM ALIGHT_PASGR_NUM WORK_DT -------- -------------- ---- -------------------- -------------- ---------------- -------- 201301 2호선 0214 강변 1565310 1549316 20130723 201301 2호선 0215 잠실나루 536413 505376 20130723 201301 2호선 0216 잠실 2323516 2106978 20130723 201301 2호선 0217 신천 814104 786397 20130723 201301 2호선 0218 종합운동장 374633 389860 20130723 201301 2호선 0219 삼성 2015421 2050988 20130723 201301 2호선 0220 선릉 1773445 1572999 20130723 201301 2호선 0221 역삼 1496812 1644097 20130723 201301 2호선 0222 강남 3453154 3558986 20130723 201301 2호선 0223 교대 1195621 1323778 20130723 10 rows selected. SQL>
Oracle SQL Developer 用于以下测试。
SQL Developer是Oracle提供的一个工具,并且是免费的。您可以从下面的 URL 下载它。
测试#1) 从ORAMSWIN949获取ORAUS7数据
您可以通过创建DL_US7 DB Link并指定DB Link“dl_us7”来检索数据。脚本如下。
CREATE DATABASE LINK DL_US7 CONNECT TO leg IDENTIFIED BY leg USING '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORAUS7) ) )' ; select use_mon, line_num, sub_sta_id, sub_sta_nm, ride_pasgr_num, alight_pasgr_num, work_dt, commt from sub_mon_stat@dl_us7 ;
执行结果中的韩文文本无法正常显示,而是显示为?(问号)字符。
通过 DB Link 导入数据时,服务器(本例中为 ORAUS7)字符集将转换为客户端(本例中为 ORAUS7)字符集。
由于以US7ASCII存储的韩文文本存储不正确,因此无法转换为MSWIN949并显示为问号。
此时若要正常显示ORAUS7韩文数据,请采用以下方法。
- 使用 UTL_RAW.CAST_TO_RAW 函数在 ORAUS7 中创建视图,以防止包含韩文字符的 VARCHAR2 数据类型列进行字符集转换。
- 将 UTL_RAW.CAST_TO_RAW 函数应用于包含韩语字符的列。
- RAW数据类型不转换字符集。
- ORAMSWIN949 查询上面创建的视图,将 RAW 数据类型转换回 VARCHAR2,并通过使用 CONVERT 函数指定源字符集和目标字符集将其转换为普通韩语。
在ORAUS7实例中,使用下面的脚本创建一个将VARCHAR2数据类型转换为RAW数据类型的视图。
-- ORAUS7에 View 생성 create or replace view vw_sub_mon_stat as select use_mon --,line_num ,utl_raw.cast_to_raw(line_num) as line_num_raw ,sub_sta_id --,sub_sta_nm ,utl_raw.cast_to_raw(sub_sta_nm) as sub_sta_nm_raw ,ride_pasgr_num, alight_pasgr_num, work_dt, commt from sub_mon_stat ;
-- ORAMSWIN949: utl_raw.cast_to_varchar2, convert 함수 적용하여 한글 데이터 정상 표시 select use_mon ,convert(utl_raw.cast_to_varchar2(line_num_raw), 'KO16MSWIN949', 'KO16MSWIN949') line_num ,sub_sta_id ,convert(utl_raw.cast_to_varchar2(sub_sta_nm_raw), 'KO16MSWIN949', 'KO16MSWIN949') sub_sta_nm ,ride_pasgr_num, alight_pasgr_num, work_dt, commt from vw_sub_mon_stat@dl_us7 a ;
执行结果以韩文正常显示如下。
测试 #2) 从 ORAUTF 获取 ORAMSWIN949 数据
在DB Link上,字符集从MSWIN949正常转换为UTF8,韩文字符导入良好。
-- ORAUTF에서 ORAMSWIN949 데이터 가져오기 select use_mon, line_num, sub_sta_id, sub_sta_nm, ride_pasgr_num, alight_pasgr_num, work_dt, commt from sub_mon_stat@dl_mswin949 ;
执行结果如下。
测试 #3) 从 ORAUTF 获取 ORAUS7 数据
如“测试 #1) 从 ORAMSWIN949 导入 ORAUS7 数据”中,韩文字符显示为 ?(问号)。
select use_mon, line_num, sub_sta_id, sub_sta_nm, ride_pasgr_num, alight_pasgr_num, work_dt, commt from sub_mon_stat@dl_us7 ;
执行结果如下。
要正常显示韩文,请使用“测试#1)从ORAMSWIN949导入ORAUS7数据”步骤中创建的视图,并稍微更改ORAUTF中通过DB Link执行的SQL的CONVERT函数参数。
-- ORAUTF: utl_raw.cast_to_varchar2, convert 함수 적용하여 한글 데이터 정상 표시 select use_mon ,convert(utl_raw.cast_to_varchar2(line_num_raw), 'AL32UTF8', 'KO16MSWIN949') line_num ,sub_sta_id ,convert(utl_raw.cast_to_varchar2(sub_sta_nm_raw), 'AL32UTF8', 'KO16MSWIN949') sub_sta_nm ,ride_pasgr_num, alight_pasgr_num, work_dt, commt from vw_sub_mon_stat@dl_us7 a ;
由于 CONVERT 函数的第二个参数指的是目标字符集,因此指定了 AL32UTF8。
执行结果如下:
参考
探索 RAW 数据类型
下面摘录了Oracle文档中有关RAW数据类型的一些内容。
资源: https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements001.htm#SQLRF50993
RAW 和 LONG RAW 数据类型
在不同系统之间移动数据时,RAW 和 LONG RAW 数据类型存储 Oracle 数据库不会显式转换的数据。 这些数据类型适用于二进制数据或字节字符串。 例如,您可以使用 LONG RAW 来存储图形、声音、文档或二进制数据数组,其解释取决于用途。
…
RAW 是一种类似于 VARCHAR2 的可变长度数据类型,不同之处在于 Oracle Net(将客户端软件连接到数据库或一个数据库连接到另一个数据库)以及 Oracle 导入和导出实用程序 传输 RAW 或 LONG RAW 数据时不执行字符转换 相比之下,如果数据在数据库之间传输,Oracle Net 和 Oracle 导入和导出实用程序会自动在不同数据库字符集之间转换 CHAR、VARCHAR2 和 LONG 数据,或者在数据库字符集和客户端字符集之间传输数据(如果传输数据)数据库和客户端之间。客户端字符集由客户端接口的类型(例如 OCI 或 JDBC)和客户端配置(例如 NLS_LANG 环境变量)决定。
上面颜色颠倒的句子的含义如下。
- 这些数据类型适用于二进制数据或字节字符串
–> RAW数据类型用于存储二进制数据。 - 传输 RAW 或 LONG RAW 数据时不执行字符转换
–> 通过DB Link(Oracle Net)传输RAW数据类型时,字符集不进行转换。
字符集转换函数 CONVERT
以下是 Oracle 文档中有关 CONVERT 函数的摘录。
资源: https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions034.htm#SQLRF00620
CONVERT 将字符串从一种字符集转换为另一种字符集。
– char 参数是要转换的值。它可以是任何数据类型 CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB 或 NCLOB。
– dest_char_set 参数是 char 转换到的字符集的名称。
– source_char_set 参数是数据库中存储 char 的字符集的名称。默认值是数据库字符集。
CHAR 和 VARCHAR2 的返回值为 VARCHAR2。对于 NCHAR 和 NVARCHAR2,它是 NVARCHAR2。对于 CLOB,它是 CLOB,对于 NCLOB,它是 NCLOB。
预防措施
RAW数据类型最多可使用2000字节。 Oracle 12c R2之后可以扩展,但一般最多2000字节。在US7ASCII中,韩文存储为2个字节,因此该方法只能应用于最多1000个韩文字符。
(如果包含英文字母和数字,可转换的字符数可能会增加。)
要转换超过 2000 字节的数据,似乎可以在 View 中将其分成两列或更多列,然后在读取 View 的实例(例如 ORAUTF)中进行转换和组合,但这尚未经过测试。
必须注意可以转换的最大字节数。