关于oracle字符集的一些事

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:27   1629   0

关于字符集的一些问题:

博主最近开始学习oracle啦,不得不说oracle的内容真的太广了,学好它不仅仅是数据库本身的问题,好多时候会牵扯各种操作系统,记得刚刚在redhat下开始安装oracle的时候差不多鼓捣了一天啊!OK,言归正传,最近博主在测试一些简单的SQL语句时发现一个问题:

哇哦,这是什么鬼,不能识别我大天朝的语言吗?吓得我赶快从网上查了查原因,貌似牵扯字符集的原因?其实很简答啦,仅仅是在安装数据库的时候字符设置默认语言没有选对!

这里字符集要解释一下:字符集(也称字元集,Character Set)就是字符编码表(codepage),一个字符不论英文、中文、韩文等在计算机系统内存或硬盘中通过二进制的字节(Byte)保存,这个二进制的编码就是字符编码(也称内码),字符集就是字符与内码的对应(映射)表。

因为多国语言的原因,就出现了根据本国语言制作的字符集。如使用最广泛的ASCII编码,由美国国家标准局(ANSI)制定,适用于所有拉丁、英文字符。中国大陆使用GB2312,GBK,GB18030等字符集,这些字符集包含所有汉字字符的内码,其中GBK,GB18030称为大字符集,对繁体中文也进行了编码。香港、台湾、澳门地区使用Big5编码,Big5收录了繁体中文(有些繁体与中国大陆繁体字符有差异)的编码,不包含简体中文的字符编码。

本段话转自:

http://www.cnblogs.com/zhwl/p/3745257.html

utf-8:可变长度,utf-8用来表示英文时,会直接使用一位字节来表示,但是查询汉字的时候可能使用多位字节来表示

utf-16:固定长度,全部使用两位字节来表示,这样的话表示英文会很占空间,但是读起来会更快

上图中database character set 即为数据库字符集的设置(要注意,以上为服务器端的字符集设置。客户端的字符集则是在用户的环境变量中),若使用默认的话,若插入数据库汉字,查询时会出现乱码的情况(原因见后面描述)。这里的选项为包含所有汉字字符的GBK字符集。

characterset:控制客户端应用程序使用的字符集。最后一个选项defult territory也好理解,这个是选择的地区,会对货币和数字格式,地区和计算星期及日期的习惯等有影响,而defualt language 有什么作用呢?它其实是对Oracle消息使用的语言,日期中月份和日显示有影响的。

服务端字符集的构成体现在数据字典表V$NLS_PARAMETERSNLS_LANGUAGENLS_TERRITORYNLS_CHARACTERSET三项取值上,其中NLS_CHARACTERSET的取值就是具体的数据库字符集。如利用查询语句SQL>SELECT * FROM V$NLS_PARAMETERS;可得到如下结果:

PARAMETER VALUE

NLS_LANGUAGE SIMPLIFIED CHINESE

NLS_TERRITORY CHINA

NLS_CHARACTERSET ZHS16GBK

即当前数据库使用的字符集是ZHS16GBK

Ps:根据ORACLE官方文档的说明,一旦数据库创建后,数据库的字符集是不能改变的。数据库服务端的字符集是在创建数据时设定的。但可通过如下方法对已设定的字符集进行修改:

方法一:重建数据库。建立数据库时将数据库的字符集设定为所需字符集。

方法二:修改SYS.PROPS$表。即用SYS用户登陆ORACLE后,利用下面语句修改相应的字符集并提交:SQL>UPDATE PROPS$ SET VALUE$=’ZHS16GBK‘WHERE NAME=’NLS_CHARACTERSET’;SQL>COMMIT;通过此种方法来更改数据库字符集,只对更改后的数据有效,即数据库中原来的数据仍以原字符集被存储。【很野的路子!改的是oracle的基表

SQL语句中可以使用:SQL>select userenv (‘language’) from dual;
来查询,比如,


查询客户端字符集:$echo $NLS_LANG $env | grep NLS_LANG

1、可以在.bash_profile 文件中添加:export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK的方法来更改(永久设置 instance级别?)

2、alter session set nls_language='american' nls_territory='america';

alter session set nls_language='american';

alter session set nls_territory='america';(session级别

操作系统字符集:

查看:echo $LANG / env | grep LANG

GDM - The GNOME Display Manager

G:图形 D:桌面 M:管理器

1、直接设置变量的方式修改,命令如下两条命令:
[root@david ~]# LANG=xxx 或者 export LANG=xxx;
[root@david ~]# LC_ALL=”xxx” 或者 export LC_ALL=”xxx”;

2、修改文件方式,通过修改/etc/sysconfig/i18n文件控制
[root@david ~]# vim /etc/sysconfig/i18n
LANG="zh_CN.GB18030" 即为系统的语言
SUPPORTED="zh_CN.UTF-8:zh_CN.GB18030:zh_CN:zh:en_US.UTF-8:en_US:en"
SYSFONT="lat0-sun16"
修改文件保存退出之后要生效要执行如下命令才可生效
[test@pan ~]$ source /etc/sysconfig/i18n

问题:

如果操作系统字符集与客户端字符集不一致会怎么样?

通过SQL> select userenv ('language') from dual;查询出USERENV('LANGUAGE')AMERICAN_AMERICA.ZHS16GBK其中AMERICAN_AMERICA是和当前session同一水平的吗(保持一致)?还是只与sever端有关系?

可以在.bash_profile 文件中添加:EXPORT NLS_LANG=AMERICAN_AMERICA.ZHS16GBK 是对instance级别客户端字符集的更改吗?

乱码的真正原因:

NLS( National Language Support)国家语言支持。NLS是数据库的一个非常强大的特性,它控制着数据的许多方面:比如数据如何存储,一般来说它控制着以下两个方面:

1文本数据持久存储在磁盘上时如何编码

2透明的将数据从一个字符集转换到另外一个字符集。

假设你在数据库中用WE8ISO8859P1 字符集存储8 位的数据,但是你的某些客户使用的是一种7位字符集,如US7ASCII字符集转换过程通常会修改数据,而你往往会把一个较大的字符集(在此例中就是8位字符集)映射到一个较小的字符集(此例中的7位字符集)。这是一种有损转换(lossy conversion),字符就会被修改,这只是因为:较小的字符集不可能表示较大字符集中的每一个字符。但是这种转换必须发生。这也是乱码产生的原因。如果数据库以一种单字节字符集存储数据,但是客户(如一个Java应用,因为Java语言使用Unicode)希望数据采用多字节表示,就必须执行转换,只有这样客户应用才能使用这些数据。http://www.cnblogs.com/kerrycode/p/3749085.html

参考文献:

http://blog.itpub.net/29519108/viewspace-1298298/(大部分是英文文献)

http://www.cnblogs.com/kerrycode/p/3749085.html(基础概念描述)

http://www.cnblogs.com/zhwl/p/3745257.htmloracle数据库文字存储解决方案,很详细的中文文献)

http://blog.csdn.net/jovitang/article/details/5174062(一位技术达人的总结)

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP