ITPub博客

首页 > 数据库 > Oracle > ORACLE 【字符集正确设置及相关操作】

ORACLE 【字符集正确设置及相关操作】

原创 Oracle 作者:哎呀我的天呐 时间:2014-11-17 14:17:06 0 删除 编辑



操作系统有自己的字符集,下面linux为例:

[oracle@ycnode1 ~]$ locale

这是因为我们在安装 Linux 时选择的是英文安装,所以默认的主语系变量是"en_US.UTF-8"。

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=

 

操作系统上查看支持所有的字符集:
linux:

[oracle@ycnode1 ~]$ locale -a

 

windows:

C:\Users\Administrator>chcp

活动代码页: 936

 

ORACLE 字符集

(1)用来存储char,varchar2,clob,long等数据类型

(2)用来标识诸如表名、列名以及PL/SQL等变量

(3)用来存储SQL和PL/SQL程序单元等。

国际字符集

(1)用以存储NCHAR、NVARCHAR2、NCLOB等数据类型。

如果一个表的类型是char,varchar2 clob long类型那么使用数据库字符集

如果表的数据类型是NCHAR、NVARCHAR2、NCLOB那么使用国家字符集

PARAMETER				 VALUE
---------------------------------------- --------------------------------------------------
NLS_LANGUAGE				 AMERICAN
NLS_TERRITORY				 AMERICA
NLS_CURRENCY				 $
NLS_ISO_CURRENCY			 AMERICA
NLS_NUMERIC_CHARACTERS			 .,
NLS_CHARACTERSET			 AL32UTF8
NLS_CALENDAR				 GREGORIAN
NLS_DATE_FORMAT 			 DD-MON-RR
NLS_DATE_LANGUAGE			 AMERICAN
NLS_SORT				 BINARY
NLS_TIME_FORMAT 			 HH.MI.SSXFF AM
PARAMETER				 VALUE
---------------------------------------- --------------------------------------------------
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			 11.2.0.4.0


国家字符集使用的比较少,一般使用的都是数据库字符集。国际字符集只是对数据库字符集的补充。

 

Oracle 的字符集命名遵循以下命名规则:

< 语言 >< 比特位数 >< 编码 >

比如: ZHS16GBK 表示采用 GBK 编码格式、 16 位(两个字节)简体中文字符集

US7ASCII   只能存储美国人使用的字符,不超过  128 个

Zhs16cgb231280  中文字符集比较老,并没有存储所有的

 

ZHS16GBK  最新的中文字符集,超集( GBK 国标)

Utf8 unicode 字符集,比如外企需求存储各国人的名字,就用 UTF8

繁体字符集,香港大五码,台湾
AL32UTF8  最全的字符集,数据库字符集用它,这个比 Utf8 多的多(跨国企业用这个,效率低)
ZHS16GBK  最新的中文字符集,超集(只存中文就用这个)
AF16UTF16 (国家字符集用它)

数据库支持这么多字符集。

SQL> select * from v$nls_valid_values where value like '%UTF%';
PARAMETER				 VALUE						    ISDEP
---------------------------------------- -------------------------------------------------- -----
CHARACTERSET				 AL24UTFFSS					    TRUE
CHARACTERSET				 UTF8						    FALSE
CHARACTERSET				 UTFE						    FALSE
CHARACTERSET				 AL32UTF8					    FALSE
CHARACTERSET				 AL16UTF16					    FALSE

如果软件有字符集,那么数据库字符集就不用了,sqlplus没有字符集,那么sqlplus使用操作系统字符集。

我们研究客户端操作系统和数据库的字符集。

sqlplus 客户端登陆服务器结构: 所有字符集的转换都在 oracle 端进行的。



你把客户端设置成16gbk ORACLE就认为客户端是16gbk,客户端真正的字符集不是这个,他的作用只是传话,使得oracle认为客户端就是16gbk

 客户端字符集通常中文字符集、utf8
 NLS_LANG的设置就是将其设置成客户端操作系统的字符集。


平时用的时候发现没有问题,客户端操作系统将”其“转换成A4,然后A4传到数据库,数据库问客户端你用什么编码编的,客户端说我用UTF8 然后oracle将A4直接存到数据库中。使用的时候不报错。
 不论oracle存储还是读取都经过NLS_LANG


[oracle@linux6 ~]$ export NLS_LANG=american_america.utf8
 

[oracle@VM-0-3-centos ~]$ export NLS_LANG=american_america.utf8
[oracle@VM-0-3-centos ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Thu Mar 25 10:39:05 2021
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> select dump('姚崇',1016) from dual;
DUMP('姚崇',1016)
--------------------------------------------------------------------------------
Typ=96 Len=6 CharacterSet=AL32UTF8: e5,a7,9a,e5,b4,87

sqlplus本身没有字符集,他参考客户端操作系统的字符集。如果软件有字符集,那么软件就不参考数据库的字符集。

所有的字符集转换都是在oracle端发生的。

当我们在sqlplus中输入中文“中国”的时候,被操作系统编码,编码出几个数字,编码从客户端传到oracle,oracle拿到编码,转化成字符集,oracle必须知道这个编码是由什么编的。

结论:如果客户端字符集和数据库字符集一样,那么数据库直接存储传过来的编码;如果客户端是zhs16gbk,数据库是utf-8,那么传过来的是zhs16gbk编码,在数据库端转化成zhs16gbk的字符,然后这些字符再转化成utf-8的编码,存储到表中。(数据库存储时,存储的是编码)

NLS_LANG 这个参数在客户端设的。oracle想要知道操作系统的字符集,这个参数设置成16gbk,那么oracle就认为你的客户端操作系统的字符集就是zhs16gbk。
NLS_LANG的参数设置的和客户端一样。

这是最隐蔽的一个错误。

SQL> select ename,job,dump(ename,1016) from emp;
ENAME  JOB        DUMP(ENAME,1016)
---------- --------- --------------------------------------------------------------------------------
姚崇    CLERK     Typ=1 Len=4 CharacterSet=ZHS16GBK: d2,a6,b3,e7
姚崇    SALESMAN  Typ=1 Len=4 CharacterSet=ZHS16GBK: d2,a6,b3,e7

16进制显示。

当存储的时候发生转换时错误的,那么这个是非常危险的!!!

SQL> select dump('姚崇',1016) from dual;
DUMP('姚崇',1016)
-----------------------------------------------
Typ=96 Len=4 CharacterSet=ZHS16GBK: d2,a6,b3,e7


windows:
set
NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

AMERICAN 的意思是oracle反馈信息,比如登录报错的提示信息是用什么语言提示的。
AMERICA 货币符号,日期格式用美国的格式,货币等等。





NLS_DATE_LANGUAGE指定用于拼写日期和月份名称以及由to_date和to_char函数返回的日期缩写(a.m.,p.m.,AD,BC)的语言。默认值来源NLS_LANGUAGE

SQL> show parameter NLS_LANGUAGE
NAME				     TYPE			       VALUE
------------------------------------ --------------------------------- ------------------------------
nls_language			     string			       AMERICAN


此初始化参数NLS_DATE_LANGUAGE的值用于初始化此参数的会话值,该值是SQL查询处理引用的实际值。如果客户端使用oracle jdbc驱动程序,或者客户端基于OCI并且定义了NLS_LANG client设置(环境变量),则此初始值将被客户端值覆盖。因此,初始化参数值通常被忽略。

SQL> show parameter nls_language
NAME				     TYPE			       VALUE
------------------------------------ --------------------------------- ------------------------------
nls_language			     string			       AMERICAN
SQL> show parameter nls_date_language
NAME				     TYPE			       VALUE
------------------------------------ --------------------------------- ------------------------------
nls_date_language		     string			       AMERICAN
SQL> select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'TUESDAY') NEXT_DAY FROM DUAL;
NEXT_DAY
---------------
17-OCT-06
SQL> select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'星期二') NEXT_DAY FROM DUAL;
select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'星期二') NEXT_DAY FROM DUAL
                                                      *
ERROR at line 1:
ORA-01846: not a valid day of the week


将nls_date_language 改成中文

SQL> alter session set nls_date_language='simplified chinese';
Session altered.
SQL> select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'星期二') NEXT_DAY FROM DUAL;
NEXT_DAY
------------
17-10月-06
SQL> select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'TUESDAY') NEXT_DAY FROM DUAL;
select next_day ( to_date ('2006-10-10','yyyy-mm-dd'),'TUESDAY') NEXT_DAY FROM DUAL
                                                      *
ERROR at line 1:
ORA-01846: not a valid day of the week


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29990276/viewspace-1336101/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: oracle 字符集
请登录后发表评论 登录
全部评论
https://cloud.tencent.com/developer/inventory/14362

注册时间:2014-10-30

  • 博文量
    403
  • 访问量
    2528654