之前就遇到过几次由于Oracle字符集引发文字化问题,稍微整理一下,作为备忘。若有不对的地方,请指出。
所谓的文字化问题,是指在根据文字编码将文字转换为相应二进制编码过程中,发生的转换失败(转换后的二经制在对应的字符编码中并不存在)问题。
由于字符集历史以及很多软件内部处理的关系,很遗憾文字化导致的问题是时有发生的。
文字化问题发生时,由于在整个文字化转换过程中有多个软件参与的原因,要定位问题发生的位置并予以处理,往往是需要花一定时间的。
本文简单说明一下对Oracle内部文字化的一些理解。
Oralce的文字编码
究竟什么是文字编码?
计算机内部,所有的数据都是以0、1的二进制序列表示(这里指的并不是文字对应的计算机内码,转换为内码的过程本文不做过多说明)。
文字也是一样,在计算机内部以某种形式的二进制序列被表示。那么某个文字究竟以哪种二进制序列被表示,这个表示规则就称作[文字编码]。
由于实际工作过程中接触的多是日文系统,所以下面以常见的日文编码为例进行说明。
文字编码 | 文字[あ]对应的二进制序列 |
SHIFT_JIS | 0x82A0 |
EUC_JP | 0xA4A2 |
UFT-8 | 0xE38182 |
表1-不同文字编码下对应的文字[あ]的二进制序列(16进制表示)
日文存在的数种字符编码,根据操作系统的不同,主要适用的字符编码也有所不同。比如,Windows系列主要以SHIFT_JIS为主,而Unix系列的操作系统则以EUC_JP或UNICODE为主。正因为如此,当文字在不同的操作系统之间传递的时候,就需要进行文字编码的变换。这里的变换是指,从某种文字编码的二进制序列变换为另一种文字编码中对应的二进制序列的过程。
例如,把文字[あ]从SHIFT_JIS编码转换为EUC_JP编码的时候,其实也就是把二进制序列0x82A0转换为0xA4A2的过程。这种变换,是依照事先规定好的变换表来进行的。变换表中记载了,变换前二进制编码和变换后二进制编码的对应关系。
※也有某些例外,不需要变换表,而是根据算数运算进行变化的。
但是,实际上也存在[在某种文字编码中存在,在另一种文字编码中不存在]的文字。
例如,Windows环境下使用的SHIFT_JIS编码中的[(1)]文字,在EUC_JP编码中一般是不存在的。
Oracle作为一款软件,搭载在各种不同的操作系统之上,根据系统文字编码的不同也需要发生也需要发生文字编码的转换。这时候就可能发生文字化的问题。
对于Oracle来说,相关的字符集可以问题两部分。
-
将数据保存到数据库中时使用的文字编码,用数据库字符集来表示。
-
客户端环境使用的文字编码,用[NLS_LANG]来表示,
数据库字符集,是在创建数据库的时候指定,决定数据最终以怎样的形式存储到数据库中,也就是数据库文件中。
而客户端环境往往是相对复杂的,可能被部署在各行中各样的操作系统之上,为了能保证不同的操作系统之上的客户端都能正常动作,所以提供了[NLS_LANG]。
图1 数据库字符集和NLS_LANG
数据库字符集
建立数据库时,需要指定一个数据库字符集。通常日语环境下,数据库字符集在数据创建之后是不能变更的。下面表2就是日语环境下常见的字符集。
数据库字符集 | 对应的文字编码 | 备注 |
JA16SJIS | SHIFT_JIS | |
JA16EUC | EUC_JP | |
JA16SJISTILDE | SHIFT_JIS | |
JA16EUCTILDE | EUC_JP | |
AL32UTF8 | UTF-8 |
表2日文环境下常见的数据库字符集