以下测试在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