以下測試在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