首页 > 代码库 > 3.放弃CHAR吧,在铸成大错之前!

3.放弃CHAR吧,在铸成大错之前!

/*************************************************
三、主题:放弃CHAR吧,在铸成大错之前!

CHAR,定长,长度不足时,会在尾部补空格。
VARCHAR,不定长,长度不一定达到最大值。
*************************************************/

=============================================================================
3.1.length,返回字符长度的函数
The LENGTH functionsreturn the length of char. LENGTH calculates length usingcharacters as defined by the input character set.
     --返回以字符为单位的长度.
LENGTHB usesbytes instead of characters.
     --返回以字节为单位的长度.
LENGTHC usesUnicode complete characters.
     --返回以Unicode完全字符为单位的长度.
LENGTH2 usesUCS2 code points.
     --返回以UCS2代码点为单位的长度.
LENGTH4 usesUCS4 code points.
    --返回以UCS4代码点为单位的长度.
=============================================================================
    CREATE TABLE TEST4
    (
      C CHAR(4),
      VC VARCHAR(4),
      NC VARCHAR(4)
    );

    INSERT INTO TEST4 VALUES(‘1‘,‘12‘,‘10‘);
    INSERT INTO TEST4 VALUES(‘3‘,‘3‘,‘210‘);
    INSERT INTO TEST4 VALUES(‘ ‘,‘110‘,‘1300‘);
    INSERT INTO TEST4 VALUES(‘25‘,‘ ‘,‘9‘); 
    INSERT INTO TEST4 VALUES(‘AA‘,‘HE‘,‘50‘);       
=============================================================================
3.2.CHAR 与 VARCHAR 的长度  
    SELECT C,LENGTH(C),VC,LENGTH(VC) FROM TEST4;--查询结果:其中有C=‘1   ‘,明显可以看到后面有空格
   
    SELECT C,LENGTH(C),LENGTHB(C),LENGTHC(C),DUMP(C),--DUMP:其中有C=‘1   ‘时,Typ=96 Len=4: 49,32,32,32,后面三个32表示空格
           VC,LENGTH(VC),LENGTHB(VC),LENGTHC(VC),DUMP(VC)--DUMP:明显的区别,实际的长度,而不是最大长度
       FROM TEST4;

3.3.比较大小(常规字符型)      
   
    SELECT C,DUMP(C)
      FROM TEST4 ORDER BY C;--排序结果:‘ ‘ ,‘1‘,‘25‘,‘3‘,‘AA‘
     
    SELECT VC,DUMP(VC)
      FROM TEST4 ORDER BY VC;--排序结果:‘ ‘,‘110‘,‘12‘,‘3‘,‘HE‘

3.4.数值在排序中的效果比较,重要应用:字符型存储数据全为数字时。
    SELECT NC,DUMP(NC)
      FROM TEST4
     ORDER BY NC;--排序结果:10,1300,210,50,9     
   --若是想将全为数字的字符型进行排序,ORDER BY C+0  或者 ORDER BY TO_NUMBER(NC) 即可
    SELECT NC,DUMP(NC)
      FROM TEST4
     ORDER BY NC+0;--排序结果:9,10,50,210,1300
  
    SELECT NC,DUMP(NC)
      FROM TEST4
     ORDER BY TO_NUMBER(NC);--排序结果:9,10,50,210,1300

3.5.字符串的比较
    填补空格的比较规则:若是长度不同,会在短的后面填补空格,等长度一致后比较;
                        自左往右顺序比较,直到比较出不一致,或者比较完成。    
   (1)单纯的字面值
      SELECT * FROM TEST4 WHERE C=‘1‘;  --能查出结果,正确的
     
   (2)VARCHAR 的值不会填补空格,所以TEST4的 CHAR ‘1   ‘ 与 TEST1的 VARCHAR2 ‘1‘ 不同  
      SELECT * FROM TEST4 WHERE C IN (SELECT NAME FROM TEST1);--0行被选择,无查询结果,其实TEST1 里面有 ‘1‘.
      --原因
      SELECT DUMP(C),DUMP(NAME)
       FROM TEST4,TEST1
      WHERE TEST4.C=‘1‘
        AND TEST1.NAME=‘1‘
     结果:Typ=96 Len=4: 49,32,32,32 ; Typ=1 Len=1: 49.
    
   (3)要想得出正确结果,所以经常有 TRIM,RPAD 函数出现,但是不推荐
      SELECT * FROM TEST4 WHERE TRIM(C) IN (SELECT NAME FROM TEST1);--TEST4 清除空格, 查询结果有值
      SELECT * FROM TEST4 WHERE C IN (SELECT RPAD(NAME,4) FROM TEST1); --TEST1 填充空格,查询结果有值

   --若是有CHAR存在,每次比较时,可能就要加上一些字符的函数。
   --CHAR浪费空间,并且可能查询中连索引都使用不上。
  
3.6.结论:放弃CHAR吧,在铸成大错之前!