[转]char,varchar2,nchar,nvarchar2讨论

char,varchar2,nchar,nvarchar2讨论


今天上午和杨老大讨论了一下char,varchar2,nchar,nvarchar2几种字符类型,发现有几种类型不大容易
分的清除,于是做了一下试验,希望能够对大家有所帮助。(高手请跳过)
如果你也搞不太清楚这几种类型,下面的东东可能对你有所帮助。
首先介绍一下环境,字符集是ZHS16GBK,国家字符集是Al16UTF16
第一步:建一张表:
SQL> create table typetest(cha char(10),varcha varchar2(10),ncha nchar(10),nvarcha 
nvarchar2(10));
表已创建。
第二步:插入一行:
SQL> insert into typetest values('a','a','a','a');
已创建 1 行。
SQL> commit;
提交完成。
然后用DUMP查看一下库中的实际存储的内容:
SQL> select dump(cha),dump(varcha),dump(ncha),dump(nvarcha) from typetest;
DUMP(CHA)                                                                       
--------------------------------------------------------------------------------
DUMP(VARCHA)                                                                    
--------------------------------------------------------------------------------
DUMP(NCHA)                                                                      
--------------------------------------------------------------------------------
DUMP(NVARCHA)                                                                   
--------------------------------------------------------------------------------
Typ=96 Len=10: 97,32,32,32,32,32,32,32,32,32                                    
Typ=1 Len=1: 97                                                                 
Typ=96 Len=20: 0,97,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32                
Typ=1 Len=2: 0,97 
发现了什么?没发现什么?滚一边去
这样我们得出了结论1:
char nchar 类型是按照定义的长度存储数据的,如果数据不够,后面补空格
varchar nvarchar2 是变长数据类型,实际长度随着存放的数据量改变
进一步思考,可以得出以下结论,用char就是空间换时间,用varchar2就是时间换空间,因为char占用较多
的空间,但是因为规则,处理起来会比较快,varchar2比较节省空间,但是处理起来比较慢,而且如果频
繁的做UPDATE还会产生行转移,会造成数据库性能下降。(什么叫行转移?你真的想知道?有空的时候来
找我,我慢慢将给你听)
接着做试验:

SQL> insert into typetest values('我','我','我','我');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select dump(cha),dump(varcha),dump(ncha),dump(nvarcha) from typetest;
DUMP(CHA)                                                                       
--------------------------------------------------------------------------------
DUMP(VARCHA)                                                                    
--------------------------------------------------------------------------------
DUMP(NCHA)                                                                      
--------------------------------------------------------------------------------
DUMP(NVARCHA)                                                                   
--------------------------------------------------------------------------------
Typ=96 Len=10: 206,210,32,32,32,32,32,32,32,32                                  
Typ=1 Len=2: 206,210                                                            
Typ=96 Len=20: 98,17,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32,0,32               
Typ=1 Len=2: 98,17    
可以看到char和varhcar是用的GBK编码的,nchar和nvarchar2是用的utf16,国家字符集进行编码的
继续向下看
SQL> insert into typetest values('我我我我我','我我我我我','我我我我我','我我我我我');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select dump(cha),dump(varcha),dump(ncha),dump(nvarcha) from typetest;                   
                                    
                                                                                
DUMP(CHA)                                                                       
--------------------------------------------------------------------------------
DUMP(VARCHA)                                                                    
--------------------------------------------------------------------------------
DUMP(NCHA)                                                                      
--------------------------------------------------------------------------------
DUMP(NVARCHA)                                                                   
--------------------------------------------------------------------------------
Typ=96 Len=10: 206,210,206,210,206,210,206,210,206,210                          
Typ=1 Len=10: 206,210,206,210,206,210,206,210,206,210                           
Typ=96 Len=20: 98,17,98,17,98,17,98,17,98,17,0,32,0,32,0,32,0,32,0,32           
Typ=1 Len=10: 98,17,98,17,98,17,98,17,98,17                                     
                                                                                
SQL> insert into typetest values('我我我我我我','我我我我我','我我我我我','我我我我我');
insert into typetest values('我我我我我我','我我我我我','我我我我我','我我我我我')
                            *
第 1 行出现错误: 
ORA-12899: 列 "COMM"."TYPETEST"."CHA" 的值太大 (实际值: 12, 最大值: 10) 

SQL> insert into typetest values('我我我我我','我我我我我','我我我我我我我我我我','我我我我
我我我我我我');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select dump(cha),dump(varcha),dump(ncha),dump(nvarcha) from typetest;
                                                                             
DUMP(CHA)                                                                       
--------------------------------------------------------------------------------
DUMP(VARCHA)                                                                    
--------------------------------------------------------------------------------
DUMP(NCHA)                                                                      
--------------------------------------------------------------------------------
DUMP(NVARCHA)                                                                   
--------------------------------------------------------------------------------
Typ=96 Len=10: 206,210,206,210,206,210,206,210,206,210                          
Typ=1 Len=10: 206,210,206,210,206,210,206,210,206,210                           
Typ=96 Len=20: 98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17      
Typ=1 Len=20: 98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17,98,17   
OK,看出结论没,char和varchar是通过数据实际占用的比特数计算长度的,nchar和nvarchar是实际能够存
放的字数为计算长度的,如果是al16utf16,那它可以存放10个汉字,那么实际占用的比特数就是20。
(可以想一想如果用UTF8做为国家字符集会产生什么样的结果)
最后讲一下,测字符串长度
你能告诉我length('我我我我我')的值是多少吗?lengthb('我我我我我')呢?lengthc('我我我我我')呢

给大家看一下结果,看看你猜的对不对
SQL> select * from typetest;
CHA        VARCHA     NCHA                 NVARCHA                              
---------- ---------- -------------------- --------------------                 
a          a          a                    a                                    
我         我         我                   我                                   
我我我我我 我我我我我 我我我我我           我我我我我                           
我我我我我 我我我我我 我我我我我我我我我我 我我我我我我我我我我    

SQL> select length(cha),length(varcha),length(ncha),length(nvarcha) from typetest;
LENGTH(CHA) LENGTH(VARCHA) LENGTH(NCHA) LENGTH(NVARCHA)                         
----------- -------------- ------------ ---------------                         
         10              1           10               1                         
          9              1           10               1                         
          5              5           10               5                         
          5              5           10              10                         
SQL> select lengthb(cha),length(varcha),length(ncha),length(nvarcha) from typetest;
LENGTHB(CHA) LENGTH(VARCHA) LENGTH(NCHA) LENGTH(NVARCHA)                        
------------ -------------- ------------ ---------------                        
          10              1           10               1                        
          10              1           10               1                        
          10              5           10               5                        
          10              5           10              10                        
                 
SQL> select lengthc(cha),lengthc(varcha),lengthc(ncha),lengthc(nvarcha) from typetest;
LENGTHC(CHA) LENGTHC(VARCHA) LENGTHC(NCHA) LENGTHC(NVARCHA)                     
------------ --------------- ------------- ----------------                     
          10               1            10                1                     
           9               1            10                1                     
           5               5            10                5                     
           5               5            10               10   
有问题欢迎和我讨论!

你可能感兴趣的:([转]char,varchar2,nchar,nvarchar2讨论)