1. 字符与编码字符是我们看到的符号的形状,而字符的编码是在某个编码格式下的对应的数字。
而编码格式本质上是一个字符和他的编码之间对应的表格。编码和解码都是查找这个表格来实现的。
编码:即根据字符查找表格得到编码数字;
解码:即根据编码数字查找表格得到字符;
注意:我们显示的和看到的都是字符,而传输和存储的都是字符的编码。
所以在存储时,是将字符查找表格得到编码,然后将编码存储在磁盘中;而在显示时,是将磁盘中的编码读出来,然后查找表格得到字符,然后将字符显示出来。
2. 软件在编码和解码时采用何种编码格式
我们知道OS有一个编码格式,那么安装在OS上的软件的编码格式有两种情况:
1)如果软件自带了编码格式,那么软件在进行编码和解码时采用的就是自己的编码格式,如不Oracle server自带了各种的编码格式,那么在Oracle服务端采用它自己的编码格式,而与安装Oracle server的OS的编码格式没有关系。
2)如果软件没有自带编码格式,那么软件在进行编码和解码时采用的就是OS的编码格式。比如sqlplus, pl/sql等软件在进行编码和解码时采用的格式就是其所在的OS的编码格式。
一般只有大型软件自带了编码格式,比如OS,Java虚拟机,Oracle server等。
我们可以用locale命令查看OS采用的编码:
[oracle@localhost ~]$ locale;
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
可以利用 locale -a 来得到OS支持的编码格式,即OS中拥有的字符编码的表格。
[oracle@localhost ~]$ locale -a
一个字符集,本质上是一张字符和编码对应的表格。
3. Oracle的数据库字符集 与 国家字符集
数据库字符集:是在存储char, varchar2, clob, long等类型的字符时,采用的编码格式。
国家字符集:是在存储nchar, nvarchar2, nclob等类型的字符时,采用的编码格式。一般很少使用。
我们可以查看Oracle server端的编码格式:
SQL> select * from nls_database_parameters;
PARAMETER VALUE
------------------------------ ------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET ZHS16GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_RDBMS_VERSION 10.2.0.1.0
20 rows selected.
可见我们数据库server端的字符集是ZHS16GBK,而国家字符集是AL16UTF16。
NLS_LANGUAGE 指语言:影响Oracle返回的提示信息和错误信息采用的语言。
NLS_TERRITORY 指地区:影响Oracle返回的信息中日期等的格式。
同样我们也可以查看某个session的字符编码信息:
SQL> select * from nls_session_parameters;
PARAMETER VALUE
------------------------------ ------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
17 rows selected.
4. 字符集的命名格式
Oracle中自带的各种字符集的命名格式如下:
language + bit size + encoding
即:语言+多少位+编码格式
比如:
ZHS16GBK表示:中文简体、16位编码、GBK编码
我们一常碰到的字符集有:
US7ASCII
AL32UTF8
AF16UTF16 (国家字符集)
ZHS16GBK (最新的中文字符集)
超级:一个字符集包含了另一个字符集的所有字符编码;
严格超级:在超级的基础上,要求两个个字符集关于同一个字符的编码值相同;
在中国,国家字符集只能选择 AF16UTF16,没有其他的选择;而对于数据库字符集,如果我们的数据库只存储中英文数据,那么我们应该选择ZHS16GBK,如果要存储其他的字符,那么应该选择AL32UTF8。比如全球性的跨国公司,那么他的数据库字符集应该选择AL32UTF8。
Oracle支持的字符集可以用下面的命令查出来:
select * from v$nls_valid_values;
PARAMETER VALUE ISDEPRECAT
------------------------------ ------------------------------ ----------
... ...
CHARACTERSET UTFE FALSE
CHARACTERSET AL32UTF8 FALSE
CHARACTERSET ZHT16HKSCS31 FALSE
CHARACTERSET JA16EUCFIXED TRUE
CHARACTERSET JA16SJISFIXED TRUE
CHARACTERSET JA16DBCSFIXED TRUE
CHARACTERSET KO16KSC5601FIXED TRUE
CHARACTERSET KO16DBCSFIXED TRUE
CHARACTERSET ZHS16CGB231280FIXED TRUE
CHARACTERSET ZHS16GBKFIXED TRUE
CHARACTERSET ZHS16DBCSFIXED TRUE
CHARACTERSET ZHT32EUCFIXED TRUE
CHARACTERSET ZHT32TRISFIXED TRUE
CHARACTERSET ZHT16DBCSFIXED TRUE
CHARACTERSET ZHT16BIG5FIXED TRUE
CHARACTERSET AL16UTF16 FALSE
... ...
5. nls_lang
因为sqlplus没有自带字符集,所以sqlplus使用的是客户端OS的字符集;而Oracle自带了字符集,那么Oracle使用自己的字符集,而与服务器OS的字符集没有关系。
当使用sqlplus将一个字符串 '中国' insert 到Oracle数据库时,sqlplus会使用其所在的OS的字符编码将 '中国' 进行编码得到编码值,然后将编码值传输到Oracle服务器;那么Oracle服务端得到编码值之后,它必须询问sqlplus客户端,知道它使用的是什么编码格式进行的编码。而sqlplus就是通过参数 nls_lang 来告诉server端,自己的编码格式。
Oracle服务端根据nls_lang知道了sqlplus客户端的编码格式,如果该编码格式与数据库的编码格式不相同,那么它会进行转码:先利用nls_lang编码格式将编码值转换成字符,然后采用数据库的编码格式将该字符转换成编码值,然后在插入到数据库中。如果nls_lang与数据库的编码格式相同,则直接将编码格式插入到数据库中。所以nls_lang参数十分重要。nls_lang一定要与sqlplus使用的编码格式相同,也就是与sqlplus所在的OS的字符集一致!
nls_lang的格式:
NLS_LANG = language_territory.clientCharacterSet
language: 决定oracle返回给sqplus的提示信息以及错误信息等;
territory: 区域,决定日期、货币等的格式;
clientCharacterSet: 客户端使用的字符编码格式;
例如:NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
AMERICAN是语言,AMERICA是地区,
ZHS16GBK 是客户端字符集
所以nls_lang就是在sqlplus客户端和Oracle服务端充当一个传递编码格式的的作用。一定不要传递错了。
只要nls_lang与客户端的编码格式一致,就不会在使用sqlplus时发生编码错误。
6. 避免编码错误
在使用sqlplus时一定要使nls_lang与客户端的编码格式一致;
最常见的一种错误是:设置nls_lang与数据库字符集一致,而与客户端字符集不一致。
另一种常见的错误是:数据库字符集选择错了,导致插入的一些字符在该字符集中不存在,那么Oracle就会插入一些???来代替。
阅读(2696) | 评论(0) | 转发(1) |