Mysql知识回顾
http://www.educity.cn/wenda/596225.html
http://blog.csdn.net/dyllove98/article/details/9289483
http://opsmysql.blog.51cto.com/2238445/1343771
http://www.cnblogs.com/lyhabc/p/3886402.html
Int(11)详解
int(11)最大长度是多少?
在SQL语句中int代表你要创建字段的类型,int代表整型,11代表字段的长度。
这个11代表显示宽度,整数列的显示宽度与mysql需要用多少个字符来显示该列数值,与该整数需要的存储空间的大小都没有关系,比如,不管设定了显示宽度是多少个字符,bigint都要占用8个字节。
int是整型,(11)是指显示字符的长度,但要加参数的,最大为255,比如它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0
声明整型数据列时,我们可以为它指定个显示宽度M(1~255),如INT(5),指定显示宽度为5个字符,如果没有给它指定显示宽度,MySQL会为它指定一个默认值。显示宽度只用于显示,并不能限制取值范围和占用空间,如:INT(3)会占用4个字节的存储空间,并且允许的最大值也不会是999,而是 INT整型所允许的最大值。
MySQL有五种整型数据列类型,即TINYINT,SMALLINT,MEDIUMINT,INT和BIGINT。它们之间的区别是取值范围不同,存储空间也各不相同。
在整型数据列后加上UNSIGNED属性可以禁止负数,取值从0开始。
int范围
Type Bytes Minimum Value Maximum Value
(Signed/Unsigned) (Signed/Unsigned)
TINYINT 1 -128 127
0 255
SMALLINT 2 -32768 32767
0 65535
MEDIUMINT 3 -8388608 8388607
0 16777215
INT 4 -2147483648 2147483647
0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807
0 18446744073709551615
zerofill实例
Int(3)在指定Zerofill的时候表示,查询结果不足3位会进行0填充,确保占用3个字符。但是超过3位的原样输出。
例如
mysql> create table tb1(a int(3) zerofill);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into tb1 values(1),(1234);
Query OK, 1 row affected (0.01 sec)
mysql> select * from tb1;
+-------+
| a |
+-------+
| 001|
| 1234 |
+-------+
1 row in set (0.00 sec)
MySQL中varchar(n)的最大长度
MySQL版本决定的varchar存储规则
(1) 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节)
(2) 5.0版本以上,varchar(20),指的是20字符,无论存放的是数字、字母还是UTF8汉字(每个汉字3字节),都可以存放20个。
后面我们只研究5.0版本以上的mysql中varchar(n)里面与n的大小有关的内容。
字符&字节
字母,汉字都是字符,字符就会有对应的编码,编码方式决定存储空间(字节)的大小。
比如,字符类型若为gbk,每个字符最多占2个字节;字符类型若为utf8,每个字符最多占3个字节。
对于非常特殊的汉字来讲,gbk汉字占用2个字节,utf8汉字占用3个字节。
而Gbk和utf8数字、字母都占用1个字节。
Char_length & byte_length
对于Varchar(n)来讲:
Char_length 【n】:字符长度(个数),不管是字母,汉字都是一个字符;
Byte_length:存储空间(字节数),跟字符编码有关系,比如UTF8汉字占用3个字节的存储空间;
比如utf8编码的‘周一001’的char_length是5,但是byte_length是9;
Char(n)和Varchar(n)
Char(n),其中n<=255,如果字符数<n,那么在内容右边填充空格,确保字符数量为n;在进行select查询时,结果最后的空格会被去除掉。CHAR存储定长数据很方便,CHAR字段上的索引效率级高。
比如定义 char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充。
VARCHAR(n)定义的列的长度为可变长字符串,n<65535(n的最大有效长度由最大行大小其他字段的长度,以及使用的字符集确定)。VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节)。VARCHAR值保存时不进行填充。当值保存和检索时尾部的空格仍保留,符合标准SQL。varchar存储变长数据,但存储效率没有 CHAR高。
如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么"+1"呢?这一个字节用于保存实际使用了多大的长度。
从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。
CHAR和VARCHAR最大的不同就是一个是固定长度,一个是可变长度。由于是可变长度,因此实际存储的时候是实际字符串再加上一个记录字符串长度的1或者2个字节(如果超过255则需要两个字节)。
如果分配给CHAR或VARCHAR列的值超过列的最大长度,则对值进行裁剪以使其适合。如果被裁掉的字符不是空格,则会产生一条警告。
规则限制
首先我们要知道,存储的最大长度(char_length)没一个固定的数值,根据不同的表结构设计有所不同,一般有以下几个限制规则:
1)行长度限制
导致实际应用中varchar长度限制的是一个行定义的长度。MySQL要求一个行的定义长度不能超过65535字节(64k)。若定义的表长度超过这个值,则提示
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。
总结一下 byte_length(row) <=65535
2)存储限制
varchar内容的存储格式为:
1或2个字节存储长度+数据内容
开始的1到2个字节表示实际长度(长度超过255时需要2个字节),之后才存储真正的数据内容。
总结:max_char_length<=65536-1-2。
第一个减1是因为实际行存储从第二个字节开始。
3)编码长度限制
字符类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766;
max_char_length(gbk)<=(65536-1-2)/2=32766
字符类型若为utf8,每个字符最多占3个字节,最大长度不能超过21844。
max_char_length(utf8)<=(65536-1-2)/3=21844
减1的原因是实际行存储从第二个字节开始;
减2的原因是varchar头部的2个字节表示长度;
除3的原因是字符编码是utf8.
Varchar转Text的条件
原则:
单行所有字段的总长度row_length<=65535;
如果单个字段varchar(n)所占用的空间>65535,则自动转为text类型。
如果一个表格只有一个varchar(n)字段,编码为utf8或者gbk;
Utf8的时候,
N |
Varchar(n)_length |
Row_length |
Result |
21844 |
21844*3=65532 |
65532+3=65535 |
刚好可以创建成功,类型为varchar |
21845 |
21845*3=65535 |
65535+3>65535 |
创建失败 |
21846 |
21846*3=65538>65535 |
varchar转换为text类型,创建成功 |
也就是说utf8的时候,N>=21846,varchar(n)单个字段超过了65535,那么会转换为text类型,因此创建成功。
gbk的时候:
N |
Varchar(n)_length |
Row_length |
Result |
32766 |
32766*2=65532 |
65532+3=65535 |
刚好可以创建成功,类型为varchar |
32767 |
32767*2=65534<65535 |
65534+3>65535 |
创建失败 |
32768 |
32768*2=65536>65535 |
varchar转换为text类型,创建成功 |
也就是说gbk的时候,N>=32768,varchar(n)单个字段超过了65535,那么会转换为text类型,因此创建成功。
Varchar(n)实例
l 实例一
若一张表中只有一个字段VARCHAR(N)类型,utf8编码或者gbk编码,则N最大值为多少?
ü Utf8编码
create table tb_name1(a varchar(N)) default charset=utf8;
则:N最大值=(65535-1-2)/3=21844
减1的原因是实际行存储从第二个字节开始;
减2的原因是varchar头部的2个字节表示长度;
除3的原因是字符编码是utf8.
mysql测试如下:
mysql> create table tb_name1(a varchar(21844)) default charset=utf8;
Query OK, 0 rows affected (0.01 sec)
mysql> drop table tb_name1;
Query OK, 0 rows affected (0.01 sec)
mysql> create table tb_name1(a varchar(21845)) default charset=utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql>
mysql> create table tb_name1(a varchar(21846)) default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show warnings;
+-------+------+--------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------+
| Note | 1246 | Converting column ‘a‘ from VARCHAR to TEXT |
+-------+------+--------------------------------------------+
1 row in set (0.00 sec)
ü gbk编码
mysql> create table tb_name1(a varchar(32766)) default charset=gbk;
Query OK, 0 rows affected (0.03 sec)
mysql> drop table tb_name1;
Query OK, 0 rows affected (0.01 sec)
mysql> create table tb_name1(a varchar(32767)) default charset=gbk;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql>
mysql> create table tb_name1(a varchar(32768)) default charset=gbk;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show warnings;
+-------+------+--------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------+
| Note | 1246 | Converting column ‘a‘ from VARCHAR to TEXT |
+-------+------+--------------------------------------------+
1 row in set (0.00 sec)
l 实例二
若一张表中有一个字段VARCHAR(N)类型,并且有其它的字段类型,utf8编码,则N的最大值为多少?
如:create table tb_name2(a int, b char(20), c varchar(N)) default charset=utf8;
则:N最大值=(65535-1-2-4-20*3)/3=21822
减1的原因是实际行存储从第二个字节开始;
减2的原因是varchar头部的2个字节表示长度;
减4的原因是a字段的int类型占4个字节;
减20*3的原因是char(20)占用60个字节,编码是utf8。
Char(20)在utf8编码下占据60个字节。
回到sql下测试下:
MariaDB [opdba]> create table tb_name2(a int, b char(20), c varchar(21822)) default charset=utf8;
Query OK, 0 rows affected (0.28 sec)
mysql> drop table tb_name2;
Query OK, 0 rows affected (0.20 sec)
mysql> create table tb_name2(a int, b char(20), c varchar(21823)) default charset=utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
mysql> create table tb_name2(a int, b char(20), c varchar(21846)) default charset=utf8;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show warnings;
+-------+------+--------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------+
| Note | 1246 | Converting column ‘c‘ from VARCHAR to TEXT |
+-------+------+--------------------------------------------+
1 row in set (0.00 sec)
l 实例三
若一张表中有多字段VARCHAR(N)类型,并且有其它的字段类型,gbk编码,则N的最大值为多少?
如:create table tb_name3(a int, b char(20), c varchar(50), d varchar(N)) default charset=gbk;
则:N最大值=(65535-1-4-20*2-1-50*2-2)/2=32693
第一个减1的原因是实际行存储从第二个字节开始;
减去4的原因是int占用4个字节;
减20*2的原因是char(20)占用40个字节,编码是gbk;
第二个减1表示varchar(50)头部一个1个字节表示长度(小于255);
减50*2的原因是varchar(50)占用100个字节,编码是gbk;
减2的原因是varchar(N)头部的2个字节表示长度(大于255);
回到SQL测试:
mysql> create table tb_name3(a int, b char(20), c varchar(50), d varchar(32693)) default charset=gbk;
Query OK, 0 rows affected (0.18 sec)
mysql> create table tb_name3(a int, b char(20), c varchar(50), d varchar(32694)) default charset=gbk;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
l 实例四
若一张表中有多字段VARCHAR(N)类型,并且有其它的字段类型,utf8编码,则N的最大值为多少?
如:create table tb_name3(a int, b char(20), c varchar(50), d varchar(N)) default charset=utf8;
则:N最大值=(65535-1-4-20*3-1-50*3-2)/3=21772
第一个减1的原因是实际行存储从第二个字节开始;
减去4的原因是int占用4个字节;
减20*3的原因是char(20)占用60个字节,编码是utf8;
第二个减1表示varchar(50)头部一个1个字节表示长度(小于255);
减50*3的原因是varchar(50)占用150个字节,编码是utf8;
减2的原因是varchar(N)头部的2个字节表示长度(大于255);
回到SQL测试:
MariaDB [opdba]> create table tb_name4(a int, b char(20), c varchar(50), d varchar(21772)) default charset=utf8;
Query OK, 0 rows affected (0.18 sec)
MariaDB [opdba]> create table tb_name4(a int, b char(20), c varchar(50), d varchar(21773)) default charset=utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
Char(n)实例
Char(n)中n的最大长度是255
mysql> create table tb_name5(a char(255)) default charset=utf8;
Query OK, 0 rows affected (0.02 sec)
mysql> drop table tb_name5;
Query OK, 0 rows affected (0.00 sec)
mysql> create table tb_name5(a char(256)) default charset=utf8;
ERROR 1074 (42000): Column length too big for column ‘a‘ (max = 255); use BLOB or TEXT instead
Blob和Text
BLOB 存储可变长度的二进制数据,比如图片数据;
TEXT只能储存纯可变长度的文本数据。