频道栏目
读书频道 > 数据库 > Mysql > MySQL技术内幕:SQL编程
2.7.3 CHAR和VARCHAR
2012-11-06 10:04:48     我来说两句
收藏   我要投稿

本文所属图书 > MySQL技术内幕:SQL编程

全书一共10章,全面探讨了MySQL中SQL编程的各种方法、技巧与最佳实践。第1章首先介绍了SQL编程的概念、数据库的应用类型以及SQL查询分析器,然后介绍了SQL编程的三个阶段,希望读者通过本书的学习能达到最后的融...  立即去当当网订购

CHAR和VARCHAR是最常使用的两种字符串类型。一般来说,CHAR(N)用来保存固定长度的字符串,VARCHAR(N)用来保存变长字符类型。对于CHAR类型,N的范围为0~255,对于VARCHAR类型,N的范围为0~65 535。CHAR(N)和VARCHAR(N)中的N都代表字符长度,而非字节长度。

注意 对于MySQL 4.1之前的版本,如MySQL 3.23和MySQL 4.0,CHAR(N)和VARCHAR(N)中的N代表字节长度。

对于CHAR类型的字符串,MySQL数据库会自动对存储列的右边进行填充(Right Padded)操作,直到字符串达到指定的长度N。而在读取该列时,MySQL数据库会自动将填充的字符删除。有一种情况例外,那就是显式地将SQL_MODE设置为PAD_CHAR_TO_FULL_LENGTH,例如:
mysql> CREATE TABLE t ( a CHAR(10));                                  
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t SELECT 'abc';
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;
*************************** 1. row ***************************
        a: abc
   HEX(a): 616263
LENGTH (a): 3
1 row in set (0.00 sec)

mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;   
*************************** 1. row ***************************
        a: abc      
   HEX(a): 61626320202020202020
LENGTH (a): 10
1 row in set (0.00 sec)

在上述这个例子中,先创建了一张表t,a列的类型为CHAR(10)。然后通过INSERT语句插入值“abc”,因为a列的类型为CHAR型,所以会自动在后面填充空字符串,使其长度为10。接下来在通过SELECT语句取出数据时会将a列右填充的空字符移除,从而得到值“abc”。通过LENGTH函数看到a列的字符长度为3而非10。

接着我们将SQL_MODE显式地设置为PAD_CHAR_TO_FULL_LENGTH。这时再通过SELECT语句进行查询时,得到的结果是“abc       ”,abc右边有7个填充字符0x20,并通过HEX函数得到了验证。这次LENGTH函数返回的长度为10。需要注意的是,LENGTH函数返回的是字节长度,而不是字符长度。对于多字节字符集,CHAR(N)长度的列最多可占用的字节数为该字符集单字符最大占用字节数*N。例如,对于utf8下,CHAR(10)最多可能占用30个字节。通过对多字节字符串使用CHAR_LENGTH函数和LENGTH函数,可以发现两者的不同,示例如下:
mysql> SET NAMES gbk;
Query OK, 0 rows affected (0.03 sec)

mysql> SELECT @a:='MySQL技术内幕';
Query OK, 0 rows affected (0.03 sec)

mysql> SELECT @a,HEX(@a),LENGTH(@a),CHAR_LENGTH(@a)\G;
***************************** 1. row ****************************
a: MySQL技术内幕
HEX(a): 4D7953514CBCBCCAF5C4DAC4BB
LENGTH (a): 13
CHAR_LENGTH(a): 9
1 row in set (0.00 sec)

变量@a是gbk字符集的字符串类型,值为“MySQL技术内幕”,十六进制为0x4D7953514CBCBCCAF5C4DAC4BB,LENGTH函数返回13,即该字符串占用13字节,因为gbk字符集中的中文字符占用两个字节,因此一共占用13字节。CHAR_LENGTH函数返回9,很显然该字符长度为9。

VARCHAR类型存储变长字段的字符类型,与CHAR类型不同的是,其存储时需要在前缀长度列表加上实际存储的字符,该字符占用1~2字节的空间。当存储的字符串长度小于255字节时,其需要1字节的空间,当大于255字节时,需要2字节的空间。所以,对于单字节的latin1来说,CHAR(10)和VARCHAR(10)最大占用的存储空间是不同的,CHAR(10)占用10个字节这是毫无疑问的,而VARCHAR(10)的最大占用空间数是11字节,因为其需要1字节来存放字符长度。

注意 对于有些多字节的字符集类型,其CHAR和VARCHAR在存储方法上是一样的,同样需要为长度列表加上字符串的值。对于GBK和UTF-8这些字符类型,其有些字符是以1字节存放的,有些字符是按2或3字节存放的,因此同样需要1~2字节的空间来存储字符的长度。这在《MySQL技术内幕:InnoDB存储引擎》一书已经进行了非常详细的阐述和证明。

虽然CHAR和VARCHAR的存储方式不太相同,但是对于两个字符串的比较,都只比较其值,忽略CHAR值存在的右填充,即使将SQL _MODE设置为PAD_CHAR_TO_FULL_LENGTH也一样,例如:
mysql> CREATE TABLE t ( a CHAR(10), b VARCHAR(10));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SELECT 'a','a';
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> SELECT a=b FROM t\G;
*************************** 1. row ***************************
a=b: 1
1 row in set (0.00 sec)

mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT a=b FROM t\G;
*************************** 1. row ***************************
a=b: 1
1 row in set (0.00 sec)
 

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:2.7.2 排序规则
下一篇:2.7.4 BINARY和VARBINARY
相关文章
图文推荐
排行
热门
最新书评
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站