37、字符集_1
字符集
在计算机里面,硬盘上,只能以数字(0、1)的形式来存储,所以计算机想要存入abc这样的字符,就需要使用字符集,将abc转换为字符集里面abc对应的数字编码,然后存到计算机里
什么时候用到字符集?
在oracle数据库的表里面,对于data和num类型的列,都不涉及到字符集的概念;但是对于char、varchar、clog等这些类型的列,就涉及到字符集的概念;
当字段是char、varchar、clog等这些列的时候,用到的字符集是数据库字符集;而,当字段是nchar、nvarcha等这些列的时候,用到的字符集是国家字符集
字符集有两个字符集:
1、数据库字符集
2、国家字符集(很少用,关注不多):一定用的是Unicode字符集
图解:
oracle数据库软件里面有好多字符集:
1、zhs16gbk:中国人用的字符集
2、al32utf8:
3、us7:美国人用的字符集
4、等等字符集
然后dbca建库的时候,oracle数据库的控制文件里面就会记录下数据库的字符集和国家字符集;然后往数据库存字符的时候,比如存字符:中,这时候oracle查了一下,数据库的字符集是:zhs16gbk,然后就在zhs16gbk字符集里面找“中”对应的编码是101,就把101存进去了;然后取的时候也是查一下控制文件中的字符集,再查一下对应的字符集,再把编码转换为对应的字符,然后取出来
修改数据库的字符集(修改两个地方):
1、修改控制文件中的字符集
2、把已经存储在数据库里面所有数据的编码修改为另外一种要存储的字符集,这显然是不现实的
因此,数据库的字符集是不能修改的
字符集的超集
比如现在数据库的字符集是zhs16gbk,然后想在数据库里存日文,或者存韩文等等其他国家的字符,就是希望数据库里面可以存储多种字符集,然后推出了一种世界通用的字符集:Unicode字符集(比如:utf8、al32utf8都是属于Unicode字符集里面的)
比如:al32utf8字符集包含zhs16gbk字符集,我们就说al32utf8是zhs16gbk的超集
严格超集
比如:al32utf8字符集包含zhs16gbk字符集,并且字符对应的编码也是一样的,我们就说al32utf8是zhs16gbk的严格超集
修改数据库字符集的时候,修改为严格超集就可以了,因为每个字符对应的编码是一样的,但是中文没有严格超集
数据库字符集的转换:
oracle数据库字符集的转换全部发生在server端(服务器端)
图解:
一个客户端连上oracle数据库,然后访问数据库里一个表的varchar列的数据(比如:中国两个字符)的时候,oracle数据库会问客户端的字符集是什么,然后客户端有一个参数:NLS_LANG,参数:NLS_LANG=american_american.zhs16gbk,客户端就会使用NLS_LANG参数回答数据库,我使用的字符集是:zhs16gbk,然后数据库的字符集也是zhs16gbk,这时候不需要字符集转换,数据库就直接把字符对应的编码存到数据库里了;
发生字符转换的情况:
假设客户端用的是utf8字符集,NLS_LANG自然也要设置为utf8,然后数据库的字符集是zhs16gbk,这时候,客户端要访问数据库的数据,数据库就问客户端,你使用的字符集是什么,客户端就回答说使用的是utf8,这时候,数据库就把zhs16gbk的编码转换为对应的字符,然后拿着转换出来的字符(中国)在utf8字符集里面找utf8里面中国对应的编码,然后再把编码传给客户端,客户端就在utf8字符集里面找到编码对应的中国两个字
客户端的NLS-LANG:反映客户端真实的字符集
现在描述一个错误的过程:
NS-LANG设置为zhs16gbk,客户端使用的字符集是utf8,数据库的字符集是zhs16gbk;然后客户端要往数据库里存字符(比如:中国两个字),客户端使用的utf8字符集进行编码的(110,198),然后传给数据库,数据库就问客户端,你使用的字符集是什么,客户端就使用NLS_LANG回应数据库,我使用的字符集是zhs16gbk,然后数据库的字符集也是zhs16gbk,就直接存进数据库了;
实际上正确的编码是:100,192,但是存为了:110,198;这时候,取的时候,数据库也会问客户端使用的字符集,使用的是utf8,数据库的也是一样的字符集,就直接把110,198传给客户端,然后在客户端的utf8字符集里面找到对应的中国两个字符,这里显示是没有问题,但是存的时候,编码存错了,使用utf8编码的,存的应该是100,192这两个编码
NLS_LANG=american_american.zhs16gbk:
第一个american表示的是国家;第二个american表示的是地区;zhs16gbk才是真正影响显示的
所以,显示乱码的时候,看看NLS_LANG是不是设置错了,NLS_LANG设置的字符集要与客户端的字符集保持一致
数据库服务器里面有字符集,所以数据库服务器所在的操作系统的字符集是什么也就无所谓了,然后有的软件没有字符集,软件就使用所在的操作系统的字符集,但是有些软件本身也有字符集,比如:Word软件就有自己的字符集,它就不使用操作系统的字符集,使用它自己本身的字符集