MySQL基础教程:关于varchar(N)

一  前言
  varchar(N) N代表什么意思,能存放多少个中文字符?属于老生常谈的问题了,今天又被一个开发同事问我关于这个问题,索性写一篇文章来具体介绍一下。

二 理论知识
 先说明一下 MySQL 历来版本对 varchar 的定义:
  4.0版本以下,varchar(50),指的是50字节,如果存放UTF8汉字时,只能存16个(每个中文3字节)
  5.0版本以上,varchar(50),指的是50字符,无论存放的是数字、字母还是UTF8中文(每个中文3字节),都可以存放50个
 存储限制
  需要额外占用字节存放字符的长度:小于255为1个字节,大于255则要2个字节
 编码限制
  gbk :每个字符最多占用2个字节
  utf8:每个字符最多占用3个字节
  utf8mb4 每个字符最多占用4个字节,中文占3个字节,emoji表情符号 占用4个字节
 长度限制
  MySQL定义行的长度不能超过65535,该数值限制了列的数目,比如char(128) utf8字符集,最多有65535/(128*3)=170个汉字。

三 测试
 环境 Server version: 5.6.26-74.0-log Percona Server 
mysql> create table  t1
    -> (id int  NOT NULL AUTO_INCREMENT    primary key,
    ->  name  varchar(10)
    -> ) engine=innodb default charset=utf8mb4;
Query OK, 0 rows affected (0.01 sec)
mysql> create table  t2
    -> (id int  NOT NULL AUTO_INCREMENT    primary key,
    ->  name  varchar(10)
    -> ) engine=innodb default charset=utf8;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t3
    -> (id int  NOT NULL AUTO_INCREMENT    primary key,
    ->  name  varchar(10)
    -> ) engine=innodb default charset=gbk;
Query OK, 0 rows affected (0.01 sec)
utf8mb4 字符集
mysql> insert into t1(name) values('abcdfeghi');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t1(name) values('abcdfeghij');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t1(name) values('abcdfeghijk');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> insert into t1(name) values('一二三四五六七八九十');
Query OK, 1 row affected (0.00 sec)
 mysql> insert into t1(name) values('一二三四五六七八九十一');
Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> show warnings;
 +---------+------+-------------------------------------------+
 | Level  | Code | Message                                  |
 +---------+------+-------------------------------------------+
 | Warning | 1265 | Data truncated for column 'name' at row 1 |
 +---------+------+-------------------------------------------+
 1 row in set (0.00 sec)
 mysql> insert into t1(name) values('0123456789');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t1(name) values('01234567890');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> select id,name,length(name),char_length(name) from t1;
 +----+--------------------------------+--------------+-------------------+
 | id | name                          | length(name) | char_length(name) |
 +----+--------------------------------+--------------+-------------------+
 |  1 | abcdfeghi                      |            9 |                9 |
 |  2 | abcdfeghij                    |          10 |                10 |
 |  3 | abcdfeghij                    |          10 |                10 |
 |  4 | 一二三四五六七八九十              |          30 |                10 |
 |  5 | 一二三四五六七八九十              |          30 |                10 |
 |  6 | 0123456789                    |          10 |                10 |
 |  7 | 0123456789                    |          10 |                10 |
 +----+--------------------------------+--------------+-------------------+
 7 rows in set (0.00 sec)
utf8 字符集
mysql> insert into t2(name) values('abcdfeghi');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t2(name) values('abcdfeghij');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t2(name) values('abcdfeghijk');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> insert into t2(name) values('一二三四五六七八九十');
Query OK, 1 row affected (0.00 sec)
 mysql> insert into t2(name) values('一二三四五六七八九十一');
Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> insert into t2(name) values('0123456789');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t2(name) values('01234567890');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> select id,name,length(name),char_length(name) from t2;
 +----+--------------------------------+--------------+-------------------+
 | id | name                          | length(name) | char_length(name) |
 +----+--------------------------------+--------------+-------------------+
 |  1 | abcdfeghi                      |            9 |                9 |
 |  2 | abcdfeghij                    |          10 |                10 |
 |  3 | abcdfeghij                    |          10 |                10 |
 |  4 | 一二三四五六七八九十              |          30 |                10 |
 |  5 | 一二三四五六七八九十              |          30 |                10 |
 |  6 | 0123456789                    |          10 |                10 |
 |  7 | 0123456789                    |          10 |                10 |
 +----+--------------------------------+--------------+-------------------+
 7 rows in set (0.00 sec)
gbk 字符集
mysql> insert into t3(name) values('abcdfeghi');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t3(name) values('abcdfeghij');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t3(name) values('abcdfeghijk');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> insert into t3(name) values('一二三四五六七八九十');
Query OK, 1 row affected (0.01 sec)
 mysql> insert into t3(name) values('一二三四五六七八九十一');
Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> insert into t3(name) values('0123456789');
 Query OK, 1 row affected (0.00 sec)
 mysql> insert into t3(name) values('01234567890');
 Query OK, 1 row affected, 1 warning (0.00 sec)
 mysql> select id,name,length(name),char_length(name) from t3;
 +----+--------------------------------+--------------+-------------------+
 | id | name                          | length(name) | char_length(name) |
 +----+--------------------------------+--------------+-------------------+
 |  1 | abcdfeghi                      |            9 |                9 |
 |  2 | abcdfeghij                    |          10 |                10 |
 |  3 | abcdfeghij                    |          10 |                10 |
 |  4 | 一二三四五六七八九十              |          20 |                10 |
 |  5 | 一二三四五六七八九十              |          20 |                10 |
 |  6 | 一二三四五六七八九十              |          20 |                10 |
 |  7 | 0123456789                    |          10 |                10 |
 |  8 | 0123456789                    |          10 |                10 |
 +----+--------------------------------+--------------+-------------------+
 8 rows in set (0.00 sec)
    从上面的测试可以看出,目前版本中 varchar(N) 定义的长度的单位是字符,length(str)表示str占用的字节数,char_length(str)表示str占用的字符数。
 不论什么字符集,对于数字和英文字母都是只占用1个字符,也占用一个字节。而中文汉字因字符集不同而不同。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4e761afe0b487e8951d550951e8902bb.html