设为首页 加入收藏

TOP

Oracle字符集、编码(二)
2015-07-24 11:22:46 来源: 作者: 【 】 浏览:12
Tags:Oracle 字符集 编码
ICODE编码标准的实现,因些可以表示世界上几乎所有的文字。

当然,如果数据库字符集本身就使了UNICODE字符集,就没有必要使用NVARCHAR2, NCHAR, NCLOB这些类型了。
?

2.字符集名称的玄机

Oracle对字符集的命名实际上有一定的规则可寻,例如:

AL32UTF8

【AL】支持所有语言(All Language)。

【32】每字符最多占用32位(4字节)。

【UTF8】编码为UTF-8。

WE8MSWIN1252

【WE】支持西欧语言(Western Europe)。

【8】每字符需要占用8位(单字节)。

【MSWIN1252】编码为CP1252。

US7ASCII

【US】表示美国(United States)。

【7】每字符需要占用7位。

【ASCII】编码为ASCII。

其它如ZHS16GBK,ZHT16BIG5,US8PC437(编码为OEM cp437),都可以类推。
?

3.例子很重要

3.1.准备两个数据库

上帝说要有例子,于是有了两个相同版本的数据库,A跟B:

\ 复制代码 SELECT parameter, VALUE
FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET')

--数据库A:
PARAMETER VALUE
------------------------------ -------------------
NLS_CHARACTERSET WE8MSWIN1252
NLS_NCHAR_CHARACTERSET AL16UTF16

--数据库B:
PARAMETER VALUE
------------------------------ -----------------
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET AL16UTF16

--在A和B中分别创建一张表。
CREATE TABLE charset_test
(id NUMBER( 4) PRIMARY KEY,
vc VARCHAR2( 20),
nvc NVARCHAR2( 20)); 复制代码


3.2.工具很重要

在测试之前,为避免工具本身的特性给人造成的困惑,介绍一下几个客户端工具对UNICODE 的支持情况:

ü SQLPLUS:不支持UNICODE字符集。是否支持中文取决于当前的OEM code page,如果是cp437,无论输入还是显示中文都是不可能的。但如果是cp936,则可以支持中文输入输出。

ü PLSQL Developer:7.0版本的查询结果窗口支持UNICODE字符集,但是编辑窗口(即输入SQL语句的窗口)不支持。8.0版完全支持UNICODE。

ü Oracle SQL Developer:查询结果窗口与编辑窗口都支持UNICODE字符集。


3.3.出现乱码了

这里使用Oracle SQL Developer,分别在A、B中插入并查询中文:

\ 复制代码 INSERT INTO charset_test VALUES( 1,'中','中');
COMMIT;

--A库
SELECT * FROM charset_test;
1 ? ?

--B库
SELECT * FROM charset_test;
1 中 中 复制代码

暂时先跳过VARCHAR2字段,先来关注NVARCHAR2字段,为什么在A库不能正常显示?无非有这几种可能:

ü 客户端操作系统不支持显示中文。

ü Oracle客户端工具(这里是Oracle SQL Developer)不支持显示中文。

ü Oracle客户端有相关设置(比如NLS_LANG)不正确。

ü 存储在数据库中的数据已经是不正确的数据。

第一点,客户端操作系统是否支持中文对运行于其上的应用程序有影响吗?应该有两种情况,一种是应用程序依赖于操作系统的中文支持;另一种是有一些软件自己带有语言包及字体(比如Adobe的一些产品,.NET程序在编译的时候也可以选择将字体文件打包进去),那么它应该不依赖于操作系统。

我猜测Oracle SQL Developer应该是属于前一种,同时我检查了操作系统,确定其已经支持东亚语言(Control panel—Regional and language options—Language tab—Supplemental languages support—Install files for East Asian languages,如果checkbox已经选中,说明已经安装东亚语言包)。

第二点,无论查询结果窗口还是编辑窗口都支持UNICODE字符集。

第三点,由于不依赖于Oracle client的OCI,客户端注册表中的NLS_LANG设置对像Oracle SQL Developer没有影响。

第四点,我们借助DUMP()函数来确定NVARCHAR2字段中具体的内容。

DUMP()的语法:DUMP( [, [, [, ]]])

其中的format参数:如果是8则表示结果使用8进制表示,如果是16则表示16进制,如果是0到16间的其它数则都使用10进制。如果是大于16的数,则分几种情况:如果是可见的ASCII字符则直接打印此字符,如果是控制字符则打印成“^x”,其它情况则把结果按16进制显示。为format加上1000则表示除了输出结果之外,还会附带输出所使用的字符集信息。

这里我们使用:

\ SELECT DUMP(nvc, 1016) FROM charset_test;
--A库
Typ= 1 Len= 2 CharacterSet=AL16UTF16: 0,bf

--B库
Typ= 1 Len= 2 CharacterSet=AL16UTF16: 4e,2d

我们知道“中”字的UTF-16编码是4E2D,显然在A库中存储的数据已经是不对的,00BF实际上就是一个倒的问号字符,其存储在数据库中的原始数据已经不对了,更何况是客户端的显示。


3.4.找不同

那么为什么两个库会不一样呢?嫌疑很快就落在了数据库字符集上,因为A和B的区别只在数据库字符集上,一个是WE8MSWIN1252,另一个是AL32UTF8。经过测试,结论是:

Oracle SQL Developer忽略NLS_LANG,字符串直接以照数据库字符集进行编码后由客户端传输到服务器端。由于A库数据库字符集不支持汉字,很不幸地被替换成了默认的BF并最终被存储到数据库中,永远地错下去。B库则相反,中文在传输的过程中“存活”下来并成功到达服务器端,最终自动转换成NVARCHAR2所用的编码并存储到库中。


3.5.如何让NVARCHAR2字段工作

看起来似乎A库中的NVARCHAR2字段永远也无法正常使用了,并非这样,对于Oracle SQL Developer,通过一些设置,就可以让NVARCHAR2可以正常地插入、查询。

找到{ORACLE_HOME}\sqldeveloper\sqldeveloper\bin\sqldeveloper.conf(依赖于你的Oracle SQL Developer安装路径),添加一行配置:

AddVMOption -Doracle.jdbc.convertNcharLiterals=tr

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Oracle单实例情况下的librarycach.. 下一篇用Navicat连接Oracle数据库时报错..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·新书介绍《Python数 (2025-12-25 04:49:47)
·怎么利用 Python 进 (2025-12-25 04:49:45)
·金融界大佬力荐,Pyt (2025-12-25 04:49:42)
·你必须要弄懂的多线 (2025-12-25 04:22:35)
·如何在 Java 中实现 (2025-12-25 04:22:32)