原文地址http://www.cnblogs.com/xrq730/p/5260294.html,转载请注明出处,谢谢!html
前言mysql
好久没写文章,也有博友在个人有些文章中留言,但愿我能够写一些文章,公司项目一直很忙,可是天天也尽可能腾出一些时间写一些东西,主要针对工做中一些经常使用的知识点系统性的梳理(可能咱们在工做中只是纯粹的使用而已,不会去进行总结、概括)。sql
本文写的内容是MySQL数据类型,以前写MySQL系列文章的时候一直忽略的一个知识点,如今想来,咱们学习一门语言,无非从两个方面入手:数据库
但愿经过一篇文章的梳理,能够把MySQL数据结构这块都概括清楚。数据结构
整型函数
先从最基本的数据类型整型提及,首先用一张表格概括一下:工具
数据类型 | 字节数 | 带符号最小值 | 带符号最大值 | 不带符号最小值 | 不带符号最大值 |
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 | 18446744073709551616 |
即便是带符号的BIGINT,其实也已是一个天文数字了,什么概念,9223372036854775807咱们随便举下例子:学习
因此从实际开发的角度,咱们必定要为合适的列选取合适的数据类型,即到底用不用获得这种数据类型?举个例子:大数据
要知道,MySQL本质上是一个存储,以Java为例,可使用byte类型的地方使用了long类型问题不大,由于绝大多数的对象在程序中都是短命对象,方法执行完毕这块内存区域就被释放了,7个字节实际上不存在浪不浪费一说。可是MySQL做为一个存储,8字节的BIGINT放那儿就放那儿了,占据的空间是实实在在的。编码
最后举个例子:
1 drop table if exists test_tinyint; 2 create table test_tinyint ( 3 num tinyint 4 ) engine=innodb charset=utf8; 5 6 insert into test_tinyint values(-100); 7 insert into test_tinyint values(255);
执行第7行的代码时候报错"Out of range value for column 'num' at row 1",即很清楚的咱们能够看到插入的数字范围越界了,这也一样反映出MySQL中整型默认是带符号的。
把第3行的num字段定义改成"num tinyint unsigned"第7的插入就不会报错了,可是第6行的插入-100又报错了,由于无符号整型是没法表示负数的。
整型(N)形式
在开发中,咱们会碰到有些定义整型的写法是int(11),这种写法从我我的开发的角度看我认为是没有多大用,不过做为一个知识点作一下讲解吧。
int(N)咱们只须要记住两点:
下面举个例子,写一段SQL:
drop table if exists test_int_width; create table test_int_width ( a int(5), b int(5) unsigned, c int(5) unsigned zerofill, d int(8) unsigned zerofill ) engine=innodb charset=utf8; insert into test_int_width values(1, 1, 1, 1111111111); select * from test_int_width;
从上面的两点,咱们应该预期结果应该是1,1,00001,1111111111
咱们看一下结果:
不符合预期是吧,由于这个问题我也有过困扰,后来查了一下貌似是Navicat工具自己的问题,咱们使用控制台就不会有这个问题了:
不过实际工做场景中反正我是没有碰到过指定zerofill的,也不知道具体应用场景,若是有使用这种写法的朋友能够留言告知具体在哪一种场景下用到了这种写法。
浮点型
整型以后,下面是浮点型,在MySQL中浮点型有两种,分别为float、double,它们三者用一张表格总结一下:
数据类型 | 字节数 | 备注 |
float | 4 | 单精度浮点型 |
double | 8 | 双精度浮点型 |
下面仍是用SQL来简单看一下float和double型数据,以float为例,double同理:
drop table if exists test_float; create table test_float ( num float(5, 2) ) engine=innodb charset=utf8; insert into test_float values(1.233); insert into test_float values(1.237); insert into test_float values(10.233); insert into test_float values(100.233); insert into test_float values(1000.233); insert into test_float values(10000.233); insert into test_float values(100000.233); select * from test_float;
显示结果为:
从这个结果咱们总结一下float(M,D)、double(M、D)的用法规则:
当咱们不指定M、D的时候,会按照实际的精度来处理。
定点型
介绍完float、double两种浮点型,咱们介绍一下定点型的数据类型decimal类型,有了浮点型为何咱们还须要定点型?写一段SQL看一下就明白了:
drop table if exists test_decimal; create table test_decimal ( float_num float(10, 2), double_num double(20, 2), decimal_num decimal(20, 2) ) engine=innodb charset=utf8; insert into test_decimal values(1234567.66, 1234567899000000.66, 1234567899000000.66); insert into test_decimal values(1234567.66, 12345678990000000.66, 12345678990000000.66);
运行结果为:
看到float、double类型存在精度丢失问题,即写入数据库的数据未必是插入数据库的数据,而decimal不管写入数据中的数据是多少,都不会存在精度丢失问题,这就是咱们要引入decimal类型的缘由,decimal类型常见于银行系统、互联网金融系统等对小数点后的数字比较敏感的系统中。
最后讲一下decimal和float/double的区别,我的总结主要体如今两点上:
日期类型
接着咱们看一下MySQL中的日期类型,MySQL支持五种形式的日期类型:date、time、year、datetime、timestamp,用一张表格总结一下这五种日期类型:
数据类型 | 字节数 | 格式 | 备注 |
date | 3 | yyyy-MM-dd | 存储日期值 |
time |
3 | HH:mm:ss | 存储时分秒 |
year | 1 | yyyy | 存储年 |
datetime | 8 | yyyy-MM-dd HH:mm:ss | 存储日期+时间 |
timestamp | 4 | yyyy-MM-dd HH:mm:ss | 存储日期+时间,可做时间戳 |
下面咱们仍是用SQL来验证一下:
drop table if exists test_time; create table test_time ( date_value date, time_value time, year_value year, datetime_value datetime, timestamp_value timestamp ) engine=innodb charset=utf8; insert into test_time values(now(), now(), now(), now(), now());
看一下插入后的结果:
MySQL的时间类型的知识点比较简单,这里重点关注一下datetime与timestamp两种类型的区别:
在实际工做中,一张表每每咱们会有两个默认字段,一个记录建立时间而另外一个记录最新一次的更新时间,这种时候可使用timestamp类型来实现:
create_time timestamp default current_timestamp comment "建立时间", update_time timestamp default current_timestamp on update current_timestamp comment "修改时间",
char和varchar类型
最后看一下经常使用到的字符型,说到MySQL字符型,咱们最熟悉的应该就是char和varchar了,关于char和varchar的对比,我总结一下:
关于第一点、第二点,稍后专门开一个篇幅解释,关于第三点,写一下SQL验证一下:
drop table if exists test_string; create table test_string ( char_value char(5), varchar_value varchar(5) ) engine=innodb charset=utf8; insert into test_string values('a', 'a'); insert into test_string values(' a', ' a'); insert into test_string values('a ', 'a '); insert into test_string values(' a ', ' a ');
使用length函数来看一下结果:
验证了咱们的结论,char类型数据并不会取最后的空格。
varchar型数据占用空间大小及可容纳最大字符串限制探究
接上一部分,咱们这部分来探究一下varchar型数据实际占用空间大小是如何计算的以及最大可容纳的字符串为多少,首先要给出一个结论:这部分和具体编码方式有关,且MySQL版本我如今使用的是5.7,固然5.0以后的都是能够的。
先写一段SQL建立表,utf8的编码格式:
drop table if exists test_varchar; create table test_varchar ( varchar_value varchar(100000) ) engine=innodb charset=utf8;
执行报错:
Column length too big for column 'varchar_value' (max = 21845); use BLOB or TEXT instead
按照提示,咱们把大小改成21845,执行依然报错:
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
改成21844就不会有问题,所以在utf8编码下咱们能够知道varchar(M),M最大=21844。那么gbk呢:
drop table if exists test_varchar; create table test_varchar ( varchar_value varchar(100000) ) engine=innodb charset=gbk;
一样的报错:
Column length too big for column 'varchar_value' (max = 32767); use BLOB or TEXT instead
把大小改成32766,也是和utf8编码格式同样的报错:
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
可见gbk的编码格式下,varchar(M)最大的M=32765,那么为何会有这样的区别呢,分点详细解释一下:
一样的,上面是表中只有varchar型数据的状况,若是表中同时存在int、double、char这些数据,须要把这些数据所占据的空间减去,才能计算varchar(M)型数据M最大等于多少。
varchar、text和blob
最后讲一讲text和blob两种数据类型,它们的设计初衷是为了存储大数据使用的,由于以前说了,MySql单行最大数据量为64K。
先说一下text,text和varchar是一组既有区别又有联系的数据类型,其联系在于当varchar(M)的M大于某些数值时,varchar会自动转为text:
因此过大的内容varchar和text没有区别,同事varchar(M)和text的区别在于:
varchar和text两种数据类型,使用建议是能用varchar就用varchar而不用text(存储效率高),varchar(M)的M有长度限制,以前说过,若是大于限制,可使用mediumtext(16M)或者longtext(4G)。
至于text和blob,简单过一下就是text存储的是字符串而blob存储的是二进制字符串,简单说blob是用于存储例如图片、音视频这种文件的二进制数据的。