oracle 字符集问题
Server and client may run in the same or different locations. when client and server use different character sets, the oracle server handles character set conversion automatically.
Territory : 不同地区支持
字符集character set 是编码, ASCII 就是一个字符集,对于英语来说。因为只有26个字母,所以ASCII这个字符集就很少,但是如果是像汉语的内容,就有很多字符。汉语:每个汉字都要对应一个编码。
Unicode 是将来的必然趋势,统一的编码标准,支持世界上绝大多数语言
创建数据库之后,基本上很难改字符集,所以,最好在创建数据库的时候就选择好字符集
Considerations:
National character set : AL16UTF16 ( 这个也是 oracle 默认的 )
nls_database_paramenters 这个数据字典可以查询目前设置的字符集
受字符集的影响和限制
字节或按照 character 来算, 初始化参数 semantic , 默认是 byte
比如,你创建一个table, 类型是 varchar2(10), 那么这里的10 到底是以 byte来衡量还是以 character来算,就要看具体的数据库设置
也可以直接给定 varchar2( 10 byte ) 或 varchar2( 10 char ) 来显示给定
字符集转换
- 存储
- 显示
如果数据库和客户端的字符集是一样的,不需要转换,而如果客户端和数据库的字符集不一样,要进行转换,转换是底层完成的。例如一个工具 SQLPLUS, 即使是在 服务器运行的 SQLplus, 那么对数据库来说也是客户端
转换过程可能出现数据丢失。原因是数据库字符集选择不当,所以数据库服务器的字符集要是客户端的超集(即包含客户端的字符集 ).
最好使 unicode. 强烈推荐
SELECT id, dump(name, 1016) from t;
查看具体的在数据库中汉子存储的情况,使用 dump函数
不做字符转换时,即相同的字符集,那么就找到对应字符集的位置,不做字符转换。 发生乱码,不是把客户端和服务器端的字符集一样不能解决乱码的问题,问题出在客户端,例如在 客户端的 SQLPLUS 设置成和客户端一样的字符集,但是 WINXP(操作系统)使用的是另一个字符集,所以显示是乱码。所以。。。综上,将客户端的操作系统的字符集,和客户端程序的字符集,还有SERVER的字符集,全部设置成一样,就不会出现乱码。
AL16 固定长度 2 or 4 个字节
UTF8 可变长度 1 or 2 or 3 字节
创建数据库时设置 字符集 ( 最关键 )
创建数据库时, 就使用这个字符集了(上图)
小修小补,已经有一个大型的数据库,后来又增加了
character set 不能选择 UTF16, 所以创建数据库后,要向上边那样设置
第 3 个解决方案对中国人有很大意义
NLS_参数 : 分别规定了显示数据的不同方面
例如 ALTER SESSION SET NLS_LANGUAGE = italian ; 同样的数据,显示的面貌不一样
每个 session 显示不一样。
两个重要参数
剩下的都能确定下来了
总控参数
参数格式是由规定的,NLS_LANG = 1部分_2部分.3部分
1部分 : language
2部分 : 地区
3部分 : 字符集
以上是设置环境变量
ALTER SESSION 会覆盖你之前的设置
以上的优先级最高,优先级最高是在SQL语句中设置
数据字典
DESC v$nls_valid_values; // 字符集种类,语言种类,排序种类,区域种类
可以查看目前数据库所设置的 字符集
1 SELECT parameter, value 2 FROM nls_database_parameters 3 WHERE parameter like '%CHARACTERSET%';
影响 oracle 数据库字符集最重要的参数是NLS_LANG 参数, 它的格式为:
NLS_LANG=languare_territory.charset 它由三部分组成(语言, 地域和字符集), 其中:
language 指定服务器消息语言,
territory 指定服务器的日期和数字格式
charset 指定字符集
例如 AMERICAN_AMERICA.ZHS16GBK
从NLS_LANG 的组成我们可以看出, 真正影响数据库字符集的其实是第三部分, 所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据, 前面影响的只是提示信息.
查询 server 端的字符集 : select userenv('language') from dual; -- 结果类似 AMERICAN_AMERICA.ZHS16GBK
查询 dmp 字符集(为了数据库之间的迁移) select nls_charset_name(to_number('0354','xxxx')) from dual; -- 结果类似 ZHS16GBK
查询 client 端字符集 : 在 windows 平台下, 就是注册表里相应 oracle home 的 NLS_LANG, 也可以在dos 里自己设置 set nls_lang=AMERICAN_AMERICA.ZHS16GBK, 这样就只影响这个窗口的环境变量.
在 unix 平台下, echo $NLS_LANG 可以看到字符集, 如果发现client 和 server 端字符集不一样, 就同意修改成 server 端字符集
字符集的转换时从子集到超集受支持. 如果两个字符集根本没有子集和超集的关系, 那么字符集的转换不受 oracle 支持. 另外不建议修改 oracle server 端的字符集.
有3个字符集
1. client 本身系统字符集
2. NLS_LANG 这个应用字符集 ( 比如你在客户端调用了 sqlplus , 那么这个应用会参考这个参数 )
3. server 端字符集
如果出现乱码, 解决方法是:
server 端字符集本身就是 AL32UTF8
将 NLS_LANG 字符集设置成 AL32UTF8 (如果不设置这个参数, 那么这个参数默认就是跟server 端相同的字符集)
将 client本身字符集, 例如 unix 平台的 LANG 设置成 AL32UTF8 或者 AL32UTF8 的子集, 就可以解决乱码问题.
Language |
Locale ID |
NLS_LANG |
English (American) |
en_US.UTF-8 |
AMERICAN_AMERICA.AL32UTF8 |
English (American) |
en_US.ISO-8859-1 |
AMERICAN_AMERICA.WE8ISO8859P1 |
English (American) |
en_US.ISO-8859-15 |
AMERICAN_AMERICA.WE8ISO8859P15 |
English (Australian) |
en_AU.UTF-8 |
ENGLISH_AUSTRALIA.AL32UTF8 |
English (Australian) |
en_AU.ISO-8859-1 |
ENGLISH_AUSTRALIA.WE8ISO8859P1 |
English (Australian) |
en_AU.ISO-8859-15 |
ENGLISH_AUSTRALIA.WE8ISO8859P15 |
English (British) |
en_GB.UTF-8 |
ENGLISH_UNITED KINGDOM.AL32UTF8 |
English (British) |
en_GB.ISO-8859-1 |
ENGLISH_UNITED KINGDOM.WE8ISO8859P1 |
English (British) |
en_GB.ISO-8859-15 |
ENGLISH_UNITED KINGDOM.WE8ISO8859P15 |
English (Ireland) |
en_IE.UTF-8 |
ENGLISH_IRELAND.AL32UTF8 |
English (Ireland) |
en_IE.ISO-8859-1 |
ENGLISH_IRELAND.WE8ISO8859P1 |
English (Ireland) |
en_IE.ISO-8859-15 |
ENGLISH_IRELAND.WE8ISO8859P15 |
German |
de_DE.UTF-8 |
GERMAN_GERMANY.AL32UTF8 |
German |
de_DE.ISO-8859-1 |
GERMAN_GERMANY.WE8ISO8859P1 |
German |
de_DE.ISO-8859-15 |
GERMAN_GERMANY.WE8ISO8859P15 |
French |
fr_FR.UTF-8 |
FRENCH_FRANCE.AL32UTF8 |
French |
fr_FR.ISO-8859-1 |
FRENCH_FRANCE.WE8ISO8859P1 |
French |
fr_FR.ISO-8859-15 |
FRENCH_FRANCE.WE8ISO8859P15 |
Italian |
it_IT.UTF-8 |
ITALIAN_ITALY.AL32UTF8 |
Italian |
it_IT.ISO-8859-1 |
ITALIAN_ITALY.WE8ISO8859P1 |
Italian |
it_IT.ISO-8859-15 |
ITALIAN_ITALY.WE8ISO8859P15 |
Spanish |
es_ES.UTF-8 |
SPANISH_SPAIN.AL32UTF8 |
Spanish |
es_ES.ISO-8859-1 |
SPANISH_SPAIN.WE8ISO8859P1 |
Spanish |
es_ES.ISO-8859-15 |
SPANISH_SPAIN.WE8ISO8859P15 |
Spanish (Mexico) |
es_MX.UTF-8 |
MEXICAN SPANISH_MEXICO.AL32UTF8 |
Spanish (Mexico) |
es_MX.ISO-8859-1 |
MEXICAN SPANISH_MEXICO.WE8ISO8859P1 |
Spanish (Mexico) |
es_MX.ISO-8859-15 |
MEXICAN SPANISH_MEXICO.WE8ISO8859P15 |
Portuguese (Brazilian) |
pt_BR.UTF-8 |
BRAZILIAN PORTUGUESE_BRAZIL.AL32UTF8 |
Portuguese (Brazilian) |
pt_BR.ISO-8859-1 |
BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1 |
Portuguese (Brazilian) |
pt_BR.ISO-8859-15 |
BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P15 |
Japanese |
ja_JP.EUC-JP |
JAPANESE_JAPAN.JA16EUC |
Japanese |
ja_JP.UTF-8 |
JAPANESE_JAPAN.AL32UTF8 |
Korean |
ko_KR.EUC-KR |
KOREAN_KOREA.KO16KSC5601 |
Korean |
ko_KR.UTF-8 |
KOREAN_KOREA.AL32UTF8 |
Chinese (simplified) |
zh_CN.GB18030 |
SIMPLIFIED CHINESE_CHINA.ZHS32GB18030 |
Chinese (simplified) |
zh_CN.UTF-8 |
SIMPLIFIED CHINESE_CHINA.AL32UTF8 |
Chinese (traditional) |
zh_TW.BIG5 |
TRADITIONAL CHINESE_TAIWAN.ZHT16BIG5 |
Chinese (traditional) |
zh_TW.UTF-8 |
TRADITIONAL CHINESE_TAIWAN |
步骤可以归纳为:找到操作系统使用的字符集,并按上表找到对应的字符集名称。2.修改客户端软件的字符集NLS_LANG环境变量设置