1. 字符集与编码常识
字符集:
人们根据需要把某些字符收集到一处,并赋以名称,于是便有了某某字符集。
例如:
ASCII:
ASCII字符集:包含大小写英文、阿拉伯数字、标点,以及一些不可见的控制符共128个。
ASCII编码:使用7位表示一个字符。编码范围是[0-127](即Hex[00-7F]),其中[0-31](Hex[00-1F])部分以及127(Hex7F)是控制符,其余的都是些可见字符。
GB2312:
GB2312字符集:ASCII字符集+7000左右汉字字符。
GB2312编码:兼容ASCII编码。对字节进行判断,如值<=127,则意义等同于ASCII编码;如值>127,则它需要跟其后的另一个字节合并表示一个字符。其理论汉字编码空间为128X256,超过3万个字符。
GBK:
GBK字符集:GB2312字符集+20000左右汉字字符。
GBK编码:兼容GB2312编码。利用了GB2312编码闲置的编码空间。
GB18030:
GB18030字符集:GBK字符集+若干汉字+若干少数民族字符,为目前国内最新的字符集。
GB18030编码:兼容GBK编码。继续利用GBK编码闲置的编码空间,对于超出编码空间的则采用4个字节表示。
BIG5:
BIG5字符集:ASCII字符集+13000左右汉字(繁体)。
BIG编码:兼容ASCII编码。其编码模式类似于GB2312.
UNICODE:(UNICODE一词在日常使用中显得宽泛、混乱,在不同的语境中可以是以下意思之一。)
UNICODE标准:由一些组织提出的一套标准,对人类文字的显示、编码等进行了一系列的规定。
UNICODE字符集:目前最新版的UNICODE字符集中已经包含各种语言的超过10万的字符。
UNICODE编码:(狭义的UNICODE编码可能指UCS-2,也可能指UTF-16;广义的UNICODE编码可以指包括以下四种在内的若干种对UNICODE标准的编码实现。)
1. UTF-32编码:固定使用4个字节来表示一个字符,存在空间利用效率的问题。
2. UTF-16编码:对相对常用的60000余个字符使用两个字节进行编码,其余的(即’补充字符supplementary characters’)使用4字节。
3. UCS-2编码:是对UNICODE早期版本的实现,它与UTF-16的唯一区别是它不包括’补充字符’,所以它对字符的编码只使用两个字节。目前此编码模式已过时。
4. UTF-8编码:兼容ASCII编码;拉丁文、希腊文等使用两个字节;包括汉字在内的其它常用字符使用三个字节;剩下的极少使用的字符使用四个字节。
ISO8859-1:(使用Oracle的同志们可能见过这个WE8ISO89859P1,没错,就是它。)
ISO8859-1字符集:ASCII字符集+若干西欧字符,例如字母?、?。
ISO8859-1编码:使用8位表示一个字符,同时移除了原ASCII编码中的控制符(即[0-31],及127)。
Code page:(可以把”code page”认为是”编码”的近义词。至于为什么有这个名称?历史遗留问题。)
ANSI code pages:你一定见过ANSI,想想另存文本文件时。ANSI code pages实际上是一系列的编码集合,根据操作系统区域设置而激活其中一种作为默认ANSI编码。例如公司电脑(英文系统)上的ANSI code page可能是1252,而家里的中文系统则可能是936。所以在家里可以用ANSI存储一个包含中文的文本文件,在公司则不行。可以在注册表键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NLS\CodePage\ACP中查看到当前使用的ANSI code page。 C#可以通过Encoding.Default查看。
OEM code pages: OEM code pages是给控制台应用程序(如SQLPLUS)使用的。除CJK环境(Chinese-Japanese-Korean)外,Windows使用不同的ANSI code page和OEM code page。例如,公司英文系统上使用的是437。可以使用CHCP命令查看当前使用的OEM code page, C#可以通过Console.OutputEncoding查看。
Code page 1252:
cp1252字符集:ASCII字符集+若干西欧字符+若干特殊符号,比如?、‰.
cp1252编码:使用8位表示一个字符。编码范围是[0-255](即Hex[00-FF]),[0-127]部分与ASCII相同,新增的大部分是西欧的字符,例如一些带上标的字母?、?,以及像这样一类特殊符号)
PS1:现实中两台PC上的code page信息
PC1:英文版Windows XP,ANSI code page=1252, OEMcode page=437
PC2:中文版Windows 7,ANSI codepage=936, OEM code page=936
PS2:cp1252与cp437编码表下载请猛击这里,早期控制台应用程序常常需要画一些粗糙的表格等等图形,所以可以在437中看到不少不同的横线竖线这一类的特殊符号。
PS3:CP1252、ISO8859-1、ASCII比较,就实际使用的编码范围来说:CP1252>ISO8859-1>ASCII。ASCII是[0-127],CP1252是[0-255],ISO8859-1则移除了cp1252中[0-31]及127这些不可见的控制符,同进移除了[128-159](即Hex[80-9F])中的特殊符号。
2. 字符集
2.1. 编码schema
§ 单字节字符集:
7bit: ASCII 7-bit American(US7ASCII)
8bit: ISO8859-1 West European(WE8ISO8859P1)、EBCDICCode Page 500 8-bit West European(WE8EBCDIC500)、DEC 8-bit WestEruopean(WE8DEC)
§ 变长多字节字符集:例如Japanese Extended UNIX Code(JEUC)、ChineseGB2312-80(GB2312-80)、AL32UTF8(UTF-8)
§ 定长多字节字符集:只有National Character Set(AL16UTF16)是定长多字节字符集,是2个字节的Unicode编码
§ Unicode(AL32UTF8,AL16UTF16,UTF8):Oracle使用AL32UTF8、UTF8、UTFE作为数据库字符集,使用AL16UTF16和UTF8作为国家语言字符集。
2.2. 数据库字符集与国家字符集比较
为什么要有两个字符集?如果我知道只需要英文,设置数据库字符集=US7ASCII,如果我知道只需要西欧字符,设置数据库字符集=WE8MSWIN1252或者WE8ISO89859P1,或者干脆就用AL32UTF8。你看,我只需要设定“数据库字符集”,那么“国家字符集”有什么必要呢?
其实,考虑到历史遗留问题以及数据库创建者们无法避免的“短视”,很多现有数据库都无法支持UNICODE字符集,例如要在现有的US7ASCII数据库字符集的数据库中存储中文,这个时候“国家字符集”+NVARCHAR2这样的组合就能救你一命了。对于数据类型为NVARCHAR2(以及NCHAR, NCLOB)的字段,它使用是国家字符集,与数据库字符集的设置无关。自9i以后,国家字符集可选的只有AL16UTF16与AL32UTF8,UTF-16与UTF-8都是UNICODE编码标准的实现,因些可以表示世界上几乎所有的文字。
当然,如果数据库字符集本身就使了UNICODE字符集,就没有必要使用NVARCHAR2, NCHAR, NCLOB这些类型了。
数据库字符集与国家字符集比较:
数据库字符集 |
国家字符集 |
在创建时定义 |
在创建时定义 |
不重建不能再改变 |
除了一些例外,不重建不能再改变 |
用char、varchar2、clob、long存放数据列 |
用NCHAR、NVARCHAR2、NCLOB存放数据列 |
可以存放变长字符集 |
可以使用AL16UTF16或者UTF8存放Unicode |
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),都可以类推。
2.3. 选择数据库字符集
因为数据库字符集是用来辨别、维护SQL与PLSQL源代码,所以,它必须是EBCDIC或者7-bit ASCCII的一个超集,这使得平台本地化,因此它不可能使用定长多字节字符作为数据库字符集(即不能用AL16UTF16来作为数据库字符集)
EBCDIC平台上不能使用基于ASCII的字符集,反之亦然
2.4. 选国家字符集
有两种选择:AL16UTF16、UTF8
如果创建数据库时没有指定国家字符集,则默认是AL16UTF16.使用NVARCHAR2等数据类型时,文本内容采用国家字符集来存储和管理,而不是默认的数据库字符集。
这取决于空间和效率的考虑,AL16UTF16是定长的(2字节),而UTF8是变长的,可以在1到3字节之间,在UTF8中欧洲字符是1到2个字节,所以相对于AL16UTF16要节省空间,而亚洲字符集则用三个字节存储,所以要比AL16UTF16要的空间多。
AL16UTF16是固定长度编码,所以会比UTF8执行的快。
3.Specifying Language-Dependent Behavior
There are threeways to specify National Language Support (NLS) parameters:
§ 服务器端的初始化参数指定默认的server环境,该默认值对客户端无效。
§ Asenvironment variables for the client to specify locale-dependent behavioroverriding the defaults set for the server。
§ As theALTER SESSIONparameter to override the default set for the client or the server
alter session最高,环境变量次之,初始化参数最低;
3.1. 对服务器进行设置
NLS_LANGUAGE初始化参数:指定消息的语言、日期和月份的名称以及他们的缩写、A.D.、B.C.等的表现形式以及默认的排序机制。
NLS_TERRITORY初始化参数:指定星期与日期的numbering,默认的日期格式、10进制字符、groupsepartor和默认的ISO、当地货币标识、星期的开始时间等.
The NLS_LANGUAGE initializationparameter determines the default values of the following parameters: NLS_DATE_LANGUAGE,NLS_SORT.
NLS_TERRITORYdetermines the default values for the following parameters: NLS_CURRENCY,NLS_ISO_CURRENCY,NLS_DATE_FORMAT, NLS_NUMBERIC_CHARCTERS.
参数 |
值 |
NLS_LANGUAGE NLS_DATE_LANGUAGE NLS_SORT |
AMERICAN AMERICAN BINARY |
NLS_TERRITORY NLS_CURRENCY NLS_ISO_CURRENCY NLS_DATE_FORMAT NLS_NUMBERIC_CHARCTERS |
AMERICAN $ AMERICAN DD-MON-RR ,. |
3.2. Specifying Language-DependentBehavior for the Session
? Environment variable:
–NLS_LANG=French_France.UTF8
? Additional environmentvariables:
–NLS_DATE_FORMAT
–NLS_DATE_LANGUAGE
–NLS_SORT
–NLS_NUMERIC_CHARACTERS
–NLS_CURRENCY
–NLS_ISO_CURRENCY
–NLS_CALENDAR
Each component controls a subset of NLSfeatures:
NLS_LANG=<language>_<territory>.<charset>
where:
Language: Overrides the value ofNLS_LANGUAGEand controls the same features as
NLS_LANGUAGE
Territory: Overrides the value ofNLS_TERRITORYand controls the same features as
NLS_TERRITORY
Charset: Specifies the character encodingscheme used by client application (usually that of the user’s terminal)
NLS_LANG defines a client terminal’s characterencoding scheme. Different clients can use
different encoding schemes. Data passedbetween the client and the server is converted
automatically between the two encodingschemes. The database encoding scheme should be a superset, or equivalent, ofall the client encoding schemes. The conversion is transparent to the clientapplication.
下面这段话说明如果数据库字符集是英文,例如WE8MSWIN1252,想要存储中文是会出现问题的:
When the databasecharacter set and the client character set are the same, Oracle assumes that thedata being sent or received is of the same character set, so no validations orconversions are performed. Although the benefit of this scenariois betterperformance, misuse can lead to possible data inconsistency problems, such asstoring data from another character set that is different from the databasecharacter set.
For example, yourdatabase character set is US7ASCIIand you are using Simplified Chinese Windowsas your client terminal. By setting NLS_LANGto SIMPLIFIED
CHINESE_HONGKONG.US7ASCIIasthe client character set, it is possible for you to store
multibyte SimplifiedChinese characters inside a single byte database. This means that Oracle willtreat these characters as single-byte US7ASCIIcharacters, and therefore, allSQL string manipulation functions such as SUBSTRor LENGTHwill be based on bytesrather than characters. All of your non-ASCII characters could be lostfollowing an export and import into another database.
3.3. Windows下常用客户端设置PL/SQL Developer
1、影响PL/SQL DEVELOPER字符集显示的要素
- OS系统当前字符集
使用chcp查看coding page,936表示操作系统当前字符集为简体中文,同ZHS16GBK..
- ORACLE注册表
在ORACLE目录下NLS_LANG,如AMERICAN_AMERICA.ZHS16GBK
该键值默认读取OS系统当前字符集,当然可以修改。
- 系统环境变量NLS_LANG
环境变量影响DOS窗口、sql*plus、PL/SQL DEVELOPER等应用.
- ORACLE数据库字符设置
select * from NLS_DATABASE_PARAMETERS n where n.PARAMETER=‘NLS_CHARACTERSET‘;
PARAMETER VALUE
NLS_CHARACTERSET ZHS16GBK
- PL/SQL DEVELOPER菜单中TOOLS中首选项的‘unicode support‘
若选中此项,将从 Oracle Server 中按原样获取 Unicode 数据,并将其显示为 Unicode
文本。若禁用此项,则来自服务器的 Unicode 数据将根据 Oracle HomeRegistry 的
NLS_LANG 键转换为 Oracle Client 的字符集。
写入中文时一定要指定环境变量NLS_LANG(注意是环境变量,不是注册表),只要指定了,输入中文便能正确写入,无其他要求。
4. 获取语言字符集信息
数据库服务器NLS_DATABASE_PARAMETERS(props$):
§ Parameter(NLS_CHARACTERSET,NLS_NCHAR_CHARCTERSET)
§ VALUE
查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
客户端字符集NLS_INSTANCE_PARAMETERS(来自于V$NLS_PARAMETERS):
§ 参数(被显式设置的初始化参数)
§ 值
会话字符集环境NLS_SESSION_PARAMETERS:
§ 参数(session parameters)
§ VALUE
V$NLS_VALID_VALUES(显示NLS data boot file,包括可能不支持的或者外部用的定义)
§ Parameter(language,sort,territory,characterset)
§ VALUE