字符长度的一些学习

以下测试在rdbms19.0.0.0中测试。

dump,length,lengthb 函数,可以参考官方文档

dump函数 :https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions055.htm#SQLRF00635
length函数: https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions088.htm#SQLRF00658

-- 查看数据库的字符集,为AL32UTF8,创建表插入汉字。

select * from nls_database_parameters where parameter='NLS_CHARACTERSET'    
create table test_char (a char(4 char),b varchar2(4),c char(4));
insert into test_char values ('我','我','');
commit;

BB@test>desc test_char
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  CHAR(4 CHAR)
 B                                                  VARCHAR2(4)
 C                                                  CHAR(4)

BB@test>

BB@test>select * from nls_database_parameters where parameter='NLS_CHARACTERSET';

PARAMETER            VALUE
-------------------- ----------
NLS_CHARACTERSET     AL32UTF8

BB@test>

SQL> insert into test_char values ('我','我','');
1 row inserted
SQL> commit;
Commit complete
SQL> select * from test_char;
A                B    C
---------------- ---- ----
我               我  
SQL> 

BB@test>select dump(a) dumpa ,length(a) lena,lengthb(a) lenba,
       dump(b) dumpb ,length(b) lenb,lengthb(b) lenbb,
       dump(c) dumpc
from test_char;  2    3    4

DUMPA                                        LENA LENBA DUMPB                          LENB LENBB DUMPC
-------------------------------------------- ---- ----- ------------------------------ ---- ----- ----------
Typ=96 Len=6: 230,136,145,32,32,32              4     6 Typ=1 Len=3: 230,136,145          1     3 NULL

BB@test>

-- 说明
typ表示当前的expr值的类型,96表示nchar,1表示varchar2[nvchar2] .
可以参考文档 :https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements001.htm#SQLRF30020
test_char表中,A字段是CHAR(4 CHAR)。存储4个字符。B字段是VARCHAR2(4),最多存储4字节,C字段CHAR(4)存储4字节。
如果字符集是AL32UTF8,因此,中文是3字节表示一个汉字。(对于汉字,ZHS16GBK编码,一个汉字需要2个字节,UTF8需要3个字节)
A列CHAR(4 CHAR),存储了4个字符的定长数据,230,136,145,32,32,32。前三个表示字符'我',后面3个32表示3个空格。一起表示4个字符的存储,length(a)=4.但因为中文字符是3字节,因此lengthb(a)=6 .
B列VARCHAR2(4)是变长,存入一个中文'我',因此实际length(b)=1,lengthb(b)=3,尾部并未存入空格字符。

目前个人理解,A字段是CHAR(4 CHAR),汉字'我'占用1个字符,其他三个字符用空格替代。而汉字1个字符是3个字节。所以3+3=6 。所以len=6
所以lengthb(a)也是6 。length(a)表示a的字符长度,定义多少就是多少。

-- 再次举例,比如下面的,A字段是char (10 char),插入'我我',占用2个char,剩余8个补充空格,每个汉字3个字节,所以2*3+8=14 。所以Len=14 。

insert into bb.test_char2 values('我我')
BB@test>select dump(a) from bb.test_char2;
DUMP(A)
--------------------------------------------------------------------------------
Typ=96 Len=14: 230,136,145,230,136,145,32,32,32,32,32,32,32,32
BB@test>desc test_char2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  CHAR(10 CHAR)
BB@test>
BB@test>select length(a),lengthb(a) from bb.test_char2;
 LENGTH(A) LENGTHB(A)
---------- ----------
        10         14
BB@test>
SQL> select dump('我') from dual;  -- 设置了正确的NLS_LANG,没有乱码,len=3 .
DUMP('我')
-------------------------
Typ=96 Len=3: 230,136,145
SQL> 
BB@test>select dump('我') from dual;    -- 这个dump结果 len=9 ,原因是没有设置正确的NLS,查询导致是乱码
DUMP('???')
-------------------------------------------------
Typ=96 Len=9: 239,191,189,239,191,189,239,191,189
BB@test>
[oracle@redhat762100 ~]$ export NLS_LANG="SIMPLIFIED CHINESE.AL32UTF8"
[oracle@redhat762100 ~]$ sqlplus /nolog
SQL*Plus: Release 19.0.0.0.0 - Production on 星期三 10月 16 10:55:39 2019 Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
@>conn bb/oracle
已连接。
BB@test>select dump('我') from dual;
DUMP('我')
-------------------------
Typ=96 Len=3: 230,136,145
BB@test>

-- 还是使用表test_char2,字段A是char(10 char),可以包含10个中文字符,比如插入10个'我',插入11个'我'提示错误

BB@test>desc test_char2
 名称                                    是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 A                                                  CHAR(10 CHAR)
BB@test>
BB@test>insert into bb.test_char2 values('我我我我我我我我我我');
已创建 1 行。
BB@test>
insert into bb.test_char2 values('我我我我我我我我我我我'); 
BB@test>insert into bb.test_char2 values('我我我我我我我我我我我');
insert into bb.test_char2 values('我我我我我我我我我我我')
                                *
第 1 行出现错误:
ORA-12899: 列 "BB"."TEST_CHAR2"."A" 的值太大 (实际值: 11, 最大值: 10)
BB@test>

--查看10个'我'的len是30(10*3=30).

BB@test>select dump('我我我我我我我我我我') from dual;

DUMP('我我我我我我我我我我')
--------------------------------------------------------------------------------
Typ=96 Len=30: 230,136,145,230,136,145,230,136,145,230,136,145,230,136,145,230,1
36,145,230,136,145,230,136,145,230,136,145,230,136,145


BB@test>

-- 再次测试,创建表,字段A为char 4(也就是4bytes),插入一个汉字'我',是没有问题的,插入2个汉字'我',提示超过长度了(因为1个汉字3个bytes)。

create table bb.test_char3(A char(4));
insert into bb.test_char3 values('我');
insert into bb.test_char3 values('我我');
BB@test>insert into bb.test_char3 values('我');
已创建 1 行。
BB@test>insert into bb.test_char3 values('我我');
insert into bb.test_char3 values('我我')
                                 *
第 1 行出现错误:
ORA-12899: 列 "BB"."TEST_CHAR3"."A" 的值太大 (实际值: 6, 最大值: 4)
BB@test>
-- 修改A的长度为6 ,就可以插入两个'我'了
BB@test>alter table bb.test_char3 modify (A char(6));
表已更改。
BB@test>insert into bb.test_char3 values('我我');
已创建 1 行。

END

发布了754 篇原创文章 · 获赞 31 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/xxzhaobb/article/details/102584772