Oracle字符集转换(九):6.如何转换用户实现的字符集(二)

上一篇文章 (Oracle字符集转换(八):六、如何转换用户实现的字符集(一)),我们来看看用户实现的字符集转换方法。您可以查看如何使用 DB Link、CTAS 和 UTL_RAW 包将 KO16MSWIN949、US7ASCII 转换为 AL32UTF8。

这是通过DB Link导入数据时转换字符集的方法。

在一台服务器上配置三个数据库实例并运行三个测试。

DB 서버, DB Link 구성, 테스트 케이스
DB服务器、DB Link配置、测试用例
  1. 从 ORAMSWIN949 导入 ORAUS7 数据
  2. 从 ORAUTF 导入 ORAMSWIN949 数据
  3. 从 ORAUTF 导入 ORAUS7 数据

可以按如下方式检查 ORAUS7 中保存的韩文数据。

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 下载它。

Oracle SQL 开发人员下载

测试#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
;

执行结果中的韩文文本无法正常显示,而是显示为?(问号)字符。

테스트 #1) ORAMSWIN949 에서 ORAUS7 데이터 가져오기 실행 결과
测试#1-1)从ORAMSWIN949导入ORAUS7数据的结果

通过 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
;

执行结果以韩文正常显示如下。

测试#1-2)通过ORAMSWIN949中的View执行ORAUS7数据导入的结果

测试 #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
;

执行结果如下。

테스트 #2) ORAUTF 에서 ORAMSWIN949 데이터 가져오기 실행 결과
测试#2)从ORAUTF导入ORAMSWIN949数据的结果

测试 #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
;

执行结果如下。

测试#3-1)从ORAUTF导入ORAUS7数据执行结果

要正常显示韩文,请使用“测试#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。

执行结果如下:

테스트 #3-2) ORAUTF 에서 View를 통해 ORAUS7 데이터 가져오기 실행 결과
测试#3-2)通过View从ORAUTF导入ORAUS7数据执行结果

参考

探索 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

Character set 변환 함수 CONVERT Syntax
字符集转换函数 CONVERT 语法

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)中进行转换和组合,但这尚未经过测试。

必须注意可以转换的最大字节数。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CN简体中文