浅谈gbase与oracle 字符集差异

字符集

字符集(Character Set):按照一定的字符编码方案,将特定的符号集编码为计算机能够处理的数值的集合。

常见字符集名称:ASCII字符集、Unicode字符集、GB2312字符集、BIG5字符集、 GB18030字符集等。

字符编码

字符编码(Character Encoding):是一套规则,对字符集进行编码的方案。
如,Unicode是字符集,UTF-8、UTF-16、UTF-32是三种字符编码方案。

Unicode 基本概念

代码点
Unicode 标准的本意很简单:希望给世界上每一种文字系统的每一个字符,都分配一个唯一的整数,这些整数叫做代码点(Code Points)。

代码空间
所有的代码点构成一个代码空间(Code Space),根据 Unicode 定义,总共有 1,114,112 个代码点,编号从 0x0-0x10FFFF。 
换句话说,如果每个代码点都能够代表一个有效字符的话,Unicode 标准最多能够编码 1,114,112,也就是大概 110 多万个字符。
最新的 Unicode 标准(7.0)已经给超过 11 万个字符分配了代码点。

代码平面
Unicode 标准把代码点分成了 17 个代码平面(Code Plane),编号为 #0-#16。每个代码平面包含 65,536(2^16)个代码点(17*65,536=1,114,112)。 
其中,Plane#0 叫做基本多语言平面(Basic Multilingual Plane,BMP),其余平面叫做补充平面(Supplementary Planes)。
Unicode7.0 只使用了 17 个平面中的 6 个,并且给这 6 个平面起了名字
Plane#0 BMP(Basic Multilingual Plane) 大部分常用的字符都坐落在这个平面内,比如 ASCII 字符,汉字等。
Plane#1 SMP(Supplementary Multilingual Plane) 这个平面定义了一些古老的文字,不常用。
Plane#2 SIP(Supplementary Ideographic Plane) 这个平面主要是一些BMP中没有包含汉字。
Plane#14 SSP(Supplementary Special-purpose Plane) 这个平面定义了一些非图形字符。
Plane#15 SPUA-A(Supplementary Private Use Area A)
Plane#16 SPUA-B(Supplementary Private Use Area B)

Unicode 编码方案


之前提到,Unicode 没有规定字符对应的二进制码如何存储。
以汉字“汉”为例,它的 Unicode 码点是 0x6c49,对应的二进制数是 110110001001001,二进制数有 15 位,这也就说明了它至少需要 2 个字节来表示。
可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。

这就导致了一些问题,计算机怎么知道你这个 2 个字节表示的是一个字符,而不是分别表示两个字符呢?

于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。
当然还有一个 UTF-32 的编码方式,也就是上述那种定长编码,字符统一使用 4 个字节,虽然看似方便,但是却不如另外两种编码方式使用广泛。

UTF-8 是一个非常惊艳的编码方式,漂亮的实现了对 ASCII 码的向后兼容,以保证 Unicode 可以被大众接受。

UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,它的最大特点就是可变长。它可以使用 1-4 个字节表示一个字符,根据字符的不同变换长度。编码规则如下:

对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。

对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设位 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。

编码规则如下:

Unicode编码(十六进制)    UTF-8 字节流(二进制)
000000-00007F            0xxxxxxx
000080-0007FF            110xxxxx 10xxxxxx
000800-00FFFF            1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF            11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF-8 的特点是对不同范围的字符使用不同长度的编码。对于 0x00-0x7F 之间的字符,UTF-8 编码与 ASCII 编码完全相同。UTF-8 编码的最大长度是 4 个字节。从上表可以看出,4 字节模板有 21 个x,即可以容纳 21 位二进制数字。Unicode 的最大码位 0x10FFFF 也只有 21 位。

例1:“汉”字的 Unicode 编码是 0x6C49。0x6C49 在 0x0800-0xFFFF 之间,使用 3 字节模板:1110xxxx 10xxxxxx 10xxxxxx。将 0x6C49 写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的 x,得到:11100110 10110001 10001001,即 E6 B1 89。

例2:Unicode 编码 0x20C30 在 0x010000-0x10FFFF 之间,使用 4 字节模板:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将 0x20C30 写成 21 位二进制数字(不足 21 位就在前面补 0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的 x,得到:11110000 10100000 10110000 10110000,即 F0 A0 B0 B0。

解码的过程也十分简单:如果一个字节的第一位是 0 ,则说明这个字节对应一个字符;如果一个字节的第一位1,那么连续有多少个 1,就表示该字符占用多少个字节。

数据库下的字符集

mysql数据库中的utf8 并不是完美实现了utf8编码方案,其不支持4字节汉字,存储四字节汉字需要使用utf8mb4

oracle 很好的实现了 utf8 utf16,utf32

gbase 完美兼容了utf8

由于gbase数据库特性,对于超长字符串不是报错而是截断

截断并非是将16进制码点机械的截断,而是将被截断字符存储为 20 

例如

create table t(c1 varchar(3));

insert into t values('');

insert into t values('a哈');

此汉字为四字节存储,对应utf8 码点为 8080 A0F0 存储失败会存储空格

浅谈gbase与oracle 字符集差异_第1张图片

数据库下的字符语义与字节语义

默认下 oracle 与gbase 默认语义为字节语义

在oracle 下可以手动设置语义,为session级

在gbase 中也可以设置字符语义,为实例级,需要配置SQL_LOGICAL_CHAR 参数

Unicode相关函数
 

在 oracle下提供了 丰富的相关函数

gbase中只有部分,例如

ascii ,LENGTH/OCTET_LENGTH/CHAR_LENGTH函数

可以按照要求返回字符/字节长度

排序规则

你可能感兴趣的:(java,前端,开发语言)