Oracle - 全角和半角

全角和半角

只有字符,数字,标点符号有全角和半角的区别,中文没有

普通写一句英文(即不要输入法):I am 28 years old, do you love me?
采用半角写:I am 28 years old, do you love me?
采用全角写:I am 28 years old,do you love me?

可以看到数字,字符,标点符号都变了样子

而输入一段中文
采用半角写:我爱你,祖国。
采用全角写:我爱你,祖国。

可以看到,对于中文来讲,不管是汉字还是标点符号,都是全角的形式。

oracle数据库中有两个函数

to_single_byte(), 将全角转为半角
to_multi_byte(), 将半角转为全角

实验一:

create table test1(id number, name varchar2(20));

insert into test1 values(1,'中国你好,我爱你');
insert into test1 values(2,'中国你好,我爱你');
insert into test1 values(3,'中国你好,我爱你');
insert into test1 values(4,'中国你好');
insert into test1 values(5,'中国你好123@$');

commit;

select id,name,dump(name,1016),dump(to_single_byte(name),1016) from test1;

1 中国你好,我爱你 Typ=1 Len=16 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,a3,ac,ce,d2,b0,ae,c4,e3 Typ=1 Len=15 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,2c,ce,d2,b0,ae,c4,e3 中国你好,我爱你
2 中国你好,我爱你 Typ=1 Len=16 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,a3,ac,ce,d2,b0,ae,c4,e3 Typ=1 Len=15 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,2c,ce,d2,b0,ae,c4,e3 中国你好,我爱你
3 中国你好,我爱你   Typ=1 Len=15 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,2c,ce,d2,b0,ae,c4,e3 Typ=1 Len=15 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,2c,ce,d2,b0,ae,c4,e3 中国你好,我爱你
4 中国你好               Typ=1 Len=8 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3 Typ=1 Len=8 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3 中国你好
5 中国你好123@$ Typ=1 Len=18 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,a3,b1,a3,b2,a3,b3,a3,c0,a1,e7 Typ=1 Len=14 CharacterSet=ZHS16GBK: d6,d0,b9,fa,c4,e3,ba,c3,31,32,33,40,a1,e7 中国你好123@$

Oracle - 全角和半角

用varchar2存的字符串,全角可以转为半角,半角也可以转为全角(这里我就不贴出来了)

实验二:

create table test(id number, name nvarchar2(20));

insert into test values(1,'中国你好,我爱你');
insert into test values(2,'中国你好,我爱你');
insert into test values(3,'中国你好,我爱你');
insert into test values(4,'中国你好');
insert into test values(5,'中国你好123@$');

select id,name,dump(name,1016),dump(to_single_byte(name),1016),to_single_byte(name) from test;

ID NAME DUMP(NAME,1016) DUMP(TO_SINGLE_BYTE(NAME),1016 TO_SINGLE_BYTE(NAME)
1 中国你好,我爱你 Typ=1 Len=16 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,c,62,11,72,31,4f,60 Typ=1 Len=17 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,c,62,11,72,31,4f,60, 中国你好,我爱你
2 中国你好,我爱你 Typ=1 Len=16 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,c,62,11,72,31,4f,60 Typ=1 Len=17 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,c,62,11,72,31,4f,60, 中国你好,我爱你
3 中国你好,我爱你 Typ=1 Len=16 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,0,2c,62,11,72,31,4f,60 Typ=1 Len=17 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,0,2c,62,11,72,31,4f,60, 中国你好,我爱你
4 中国你好 Typ=1 Len=8 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d Typ=1 Len=9 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d, 中国你好
5 中国你好123@$ Typ=1 Len=18 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,11,ff,12,ff,13,ff,20,ff,4 Typ=1 Len=19 CharacterSet=AL16UTF16: 4e,2d,56,fd,4f,60,59,7d,ff,11,ff,12,ff,13,ff,20,ff,4, 中国你好123@$

可以看到使用了to_single_byte函数好像没什么改变,显示出来的东西都是一样,但是在末尾添了个0

用select * from test where to_single_byte(name)='中国你好,我爱你',却查不到任何结果。这里特别需要小心,使用了to_single_byte函数,显示出来的结果,跟它实际的编码是不一样的。

这里需要使用select * from test where to_single_byte(to_char(name))='中国你好,我爱你',to_char这里将name字段的nvarchar转化为varchar

总结:

建议大家在使用字符串时,不管中文英文最好使用varchar2,nvarchar的确有很多坑。(备注:我的实验是在11.2.0.4做出来的,有朋友说12c不存在后面添加0的现象,可能是11g的一个小bug)

后记:

有时候如果应用报错ORA-29275: partial multibyte character,可以根据这个思路来

上一篇:理解JVM之JAVA运行时内存区域


下一篇:Java运行时内存划分与垃圾回收--以及类加载机制基础