MySQL快速入门04----数据类型
2016-08-04 12:05
585 查看
一 MySQL数据类型分类
由上图可以看到,MySQL的数据类型可以分为三大类:数值型,时间日期型和字符创型,接下来我们分别讲解这三种类型。
二 数值型
2.1 整数型
整数类型可以分为以下几种:可使用unsigned控制是否有正负
可以使用zerofill来进行前导零填充
也存在 布尔bool类型,但是就是tinyint(1)的别名
整数:
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
INT[(M)] [UNSIGNED] [ZEROFILL] 也可以使用 INTEGER
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
其中M,表示显示宽度,显示宽度不限制数值的范围。配合zerofill来使用,可以在小于显示宽度的位数前增加0.zerofill自动为unsigned,其中unsigned 表示无符号,只表示正数。
2.1.1 无格式控制
创建一个表,表中有两种类型的数据,一种为tinyint型,另外一种为int型数据,都是有符号类型且无填充的。mysql> create table if not exists int_1( -> `numA` tinyint, -> `numB` int -> ); Query OK, 0 rows affected (0.05 sec)
向该表中插入数据
mysql> insert into int_1 values(100, 101);
mysql> insert into int_1 values(1, 12);
mysql> insert into int_1 values(-1, 12);
数据展示:
mysql> select * from int_1; +------+------+ | numA | numB | +------+------+ | 100 | 101 | | 1 | 12 | | -1 | 12 | +------+------+ 3 rows in set (0.00 sec)
从展示的数据可以看出,默认的行为是有符号类型的,没有填充的类型。
对于有符号类型,tinyint占用一个字节,取值范围为-128~127;而int占用四个字节,取值范围为-32768~32767;
mysql> insert into int_1 values(127, 12); Query OK, 1 row affected (0.03 sec) mysql> insert into int_1 values(128, 12); ERROR 1264 (22003): Out of range value for column 'numA' at row 1 mysql> insert into int_1 values(-128, 12); Query OK, 1 row affected (0.02 sec) mysql> insert into int_1 values(-129, 12); ERROR 1264 (22003): Out of range value for column 'numA' at row 1从上述内容可以看到,MySQL对于插入超出范围的数的处理方式时报错!不会像CPP语言一样溢出!!!
2.1.2 有格式控制
创建表int_2,控制显示数字的最小宽度为3,无符号类型,用前导零来填充;mysql> create table if not exists int_2( -> `numA` tinyint(3) unsigned zerofill, -> `numB` int(3) unsigned zerofill -> ); Query OK, 0 rows affected (0.06 sec)
插入数据
mysql> insert into int_2 values(1, 1);
mysql> insert into int_2 values(12, 1234);
数据展示:
mysql> select * from int_2; +------+------+ | numA | numB | +------+------+ | 001 | 001 | | 012 | 1234 | +------+------+ 2 rows in set (0.00 sec)从数据展示中我们可以看出,通过规定数据的显示宽度可以达到统一显示的目的,类型(M)表示的显示的最小宽度是多少,不会影响宽度大于M的数字。
而想要实现这种自定义显示宽度的效果,就需要前导零填充,我们称之为zerofill。
注意:
设置宽度显示不影响数的取值范围,数的取值范围是有数据类型决定的;
设置显示宽度不会发生数据截取的现象。
2.2 小数型
小数型可以用(M,D)控制数值的范围;
可以是无符号的;
可以zerofill;
可以使用无符号数
单精度:FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
双精度:DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
其中M表示总的位数,D表示小数位数。此M,D可以控制保存的范围。Float(10,2) -99999999.99 到 99999999.99
如果省略M,D会根据计算机硬件进行处理。单精度,M大约为7左右;而双精度,M大约为15左右。
定点数:DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
其中M表示总的位数,D表示小数位数。此M,D可以控制保存的范围。
M,D省略,默认为10,0;
注意:可以unsigned 但是不会影响范围。
2.2.1 float类型和double类型
NO1 创建一个没有空格控制的float表mysql> create table if not exists float_1( -> `fl` float, -> `f2` double -> ); Query OK, 0 rows affected (0.06 sec)创建一个没有格式控制的表,表中有两种数据类型,一种为float类型,另外一种为double类型,都是有符号类型,没有填充的;
向该表中插入数据:
mysql> insert into float_1 values(12.123, 1234.5678); mysql> insert into float_1 values(-12.123, -1234.5678);
数据展示:
mysql> select * from float_1; +---------+------------+ | fl | f2 | +---------+------------+ | 12.123 | 1234.5678 | | -12.123 | -1234.5678 | +---------+------------+ 2 rows in set (0.00 sec)
控制数值的范围(和整型不同),type(M,D)表示小数位数最多为三位,整数部分最多为M-D位,超过这么多位的情况下会提示插入数据错误,当然了,如果插入的数据超过了数据的取值范围的话也会发生错误。(M表示所有的数值位数,不包含小数点和符号;D表示允许的小数位数)。
创建一个拥有格式控制的float表
mysql> create table if not exists float_2( -> `f1` float(5,2) zerofill, -> `f2` double(6,3) zerofill -> ); Query OK, 0 rows affected (0.06 sec)
上方的表中f1中可以有五位数,小数点占两位、整数占三位,当填充的数字不足时用前导零来填充
上方的表中f2中可以有六位数,小数点占三位、整数占三位,当填充的数字不足时用前导零来填充
向里边插入数据:
mysql> insert into float_2 values(12.34, 12.34);
mysql> insert into float_2 values(1.1, 1.2);
mysql> insert into float_2 values(123.45, 123.456);
数据展示:
mysql> select * from float_2; +--------+---------+ | f1 | f2 | +--------+---------+ | 12.34 | 12.340 | | 01.10 | 01.200 | | 123.45 | 123.456 | +--------+---------+ 3 rows in set (0.00 sec)
注意:当插入数据的位数超过规定的额定值以后,插入出错!
mysql> insert into float_2 values(123456.1, 123456.34); ERROR 1264 (22003): Out of range value for column 'f1' at row 1
mysql> insert into float_2 values(1234.12, 123456.34); ERROR 1264 (22003): Out of range value for column 'f1' at row 1
NO2 浮点数的科学计数发(E)
浮点数支持科学计数法,如插入数据时:
mysql> insert into float_2 values(0.1234E2, 0.123456E3); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from float_2; +--------+---------+ | f1 | f2 | +--------+---------+ | 12.34 | 12.340 | | 01.10 | 01.200 | | 123.45 | 123.456 | | 12.34 | 123.456 | +--------+---------+ 4 rows in set (0.00 sec)
当向表中插入的小数点位数多余分配的位数的时候,小数点会四舍五入!
mysql> insert into float_2 values(12.126, 12.34); Query OK, 1 row affected (0.02 sec)
数据展示:
| 12.13 | 12.340 | +--------+---------+
2.2.2 定点数
定点数应对精度要求特别高的情况,由自己设定,不会出现字符串丢失的情况。decimal(M,D),其中M表示总的位数,D表示小数位数。
注意:
小数超过位数的话会出现四舍五入的情况,不会报错;
默认情况下,M为10,D为0;
创建一个定点数表:
mysql> create table if not exists float_3( -> `f` decimal(10,4) unsigned zerofill -> ); Query OK, 0 rows affected (0.07 sec)
插入数据:
mysql> insert into float_3 values(123.45);
mysql> insert into float_3 values(123.4567);
mysql> insert into float_3 values(123.45678);
数据展示:
mysql> select * from float_3; +-------------+ | f | +-------------+ | 000123.4500 | | 000123.4567 | | 000123.4568 | +-------------+ 3 rows in set (0.00 sec)
2.3 时间日期
DATETIME,TIMESTAMP,DATE,在保存数据时,针对数据格式与合法性进行验证,不对日期时间的合法性进行验证。
年月日时分秒的分隔符可以是任意的标点,但是常用的是-和:,甚至是不使用都可以。
2位的年也是被允许的,但是表示的范围70-69 表示:1970-2069范围
TIMESTAMP:时间戳,年份是一个范围
TIME:TIME类型不仅可以用于表示一天的时间,还可以表示一个间隔时间(或者过去了多久)
因此该类型可以设置为多个小时,甚至是 几天几小时几分钟几秒的情况 D HH:II:SS。
同样在设置时分秒时,可以使用其他标点符号作为分隔符,甚至是不用(用天了就不行了)。
2.3.1 Datetime(年月日时分秒)
范围是:支持任意分隔符的日期,也可以不加分隔符,也就是说只要有分隔符即可!但是日期范围必须要正确,如月份不能超过12创建一个时间表date_1:
mysql> create table if not exists date_1( -> myDate datetime -> ); Query OK, 0 rows affected (0.05 sec)
向时间表中插入数据:
mysql> insert into date_1 values('20160803142011'); Query OK, 1 row affected (0.02 sec) mysql> insert into date_1 values(20160803142015); Query OK, 1 row affected (0.01 sec) mysql> insert into date_1 values('2016-08-03 14:20:25'); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from date_1; +---------------------+ | myDate | +---------------------+ | 2016-08-03 14:20:11 | | 2016-08-03 14:20:15 | | 2016-08-03 14:20:25 | +---------------------+ 3 rows in set (0.00 sec)从上方我么可以看到,插入的时间必须要在一定的范围之内,插入时间的格式多种多样,既可以是字符串(用单引号引起来),也可以是单纯的整数,同时也可以使用分隔符(使用分隔符的时候相当于使用字符串,一定要用单引号引起来);
注意:
插入的时间一定要在其允许的范围之内;
分隔符可以是任意的字符,但是为了方便起见,在年份中一般用‘-’,在时间中一般用‘:’。
时间值是可以有零值的,插入零值:
mysql> insert into date_1 values(0);
零值展示:
| 0000-00-00 00:00:00 |
插入的数据也可以是不完全的,例如:
mysql> insert into date_1 values('16:08:03'); Query OK, 1 row affected (0.03 sec)
数据展示(默认插入的为年月日,其实就是从前往后进行推算):
| 2016-08-03 00:00:00 |
2.3.2 时间戳timestamp(年月日时分秒/整数)
存储时用整数、字符串都可以,表示日期和时间;范围是:支持任意分隔符的日期,也可以不加分隔符,也就是说只要有分隔符即可!但是日期范围必须要正确,如月份不能超过12。
创建时间戳表date_2:
mysql> create table if not exists date_2( -> `t` timestamp -> ); Query OK, 0 rows affected (0.14 sec)
向时间戳表date_2中插入数据:
mysql> insert into date_2 values(20160803143415); Query OK, 1 row affected (0.02 sec) mysql> insert into date_2 values('20160803143420'); Query OK, 1 row affected (0.02 sec)
mysql> insert into date_2 values('2016-08-03 14:34:25'); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from date_2; +---------------------+ | t | +---------------------+ | 2016-08-03 14:34:15 | | 2016-08-03 14:34:20 | | 2016-08-03 14:34:25 | +---------------------+ 3 rows in set (0.00 sec)从上方代码可以看到,时间戳和方法和datetime是一致的,这里不再详细赘述!
与datetime不同的一点是:检索列时,+0 可以检索时间戳,其实是一个整数的形式(去掉了连接符号)
其次就是表示的范围不一样,这是由所占用的字节数决定的。
mysql> select t+0 from date_2; +----------------+ | t+0 | +----------------+ | 20160803143415 | | 20160803143420 | | 20160803143425 | +----------------+ 3 rows in set (0.00 sec)
2.3.3 date(年月日)
创建日期表date_3:mysql> create table if not exists date_3( -> `t` date -> ); Query OK, 0 rows affected (0.05 sec)
插入数据:
mysql> insert into date_3 values(20160803); Query OK, 1 row affected (0.03 sec) mysql> insert into date_3 values('20160803'); Query OK, 1 row affected (0.03 sec) mysql> insert into date_3 values('2016:08:03'); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from date_3; +------------+ | t | +------------+ | 2016-08-03 | | 2016-08-03 | | 2016-08-03 | +------------+ 3 rows in set (0.00 sec)
其实上述三种时间数据类型还支持2为年份的插入方式(不建议使用):
mysql> insert into date_3 values('16:08:03'); Query OK, 1 row affected (0.03 sec)
mysql> insert into date_3 values('80:08:03'); Query OK, 1 row affected (0.03 sec)
数据展示:
| 2016-08-03 | | 1980-08-03 |
70-69 1970 - 2069
70-99 19xx(默认)
0-69 20xx年(默认)
语法上没有错误,但是不建议使用!
2.3.4 time(时间)
表示的意义:1,一天中的时间
2,表示时间间隔,在表示间隔时(也就是过去了多长时间),
可以使用天来表示。格式:
D HH:MM:SS
D表示天(最大为34)
创建时间表date_4:
mysql> create table if not exists date_4( -> `t` time -> ); Query OK, 0 rows affected (0.07 sec)
插入数值:
mysql> insert into date_4 values('14:55:27'); Query OK, 1 row affected (0.03 sec) mysql> insert into date_4 values('5 14:55:27'); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from date_4; +-----------+ | t | +-----------+ | 14:55:27 | | 134:55:27 | +-----------+ 2 rows in set (0.00 sec)第一条表示插入的时间数值;
第二条表示已经过去了多长时间。
2.3.5 year(年)
由于year只占用一个字节,只能表示1901-2155的取值范围。创建一个year表date_5:
mysql> create table if not exists date_5( -> `y` year -> ); Query OK, 0 rows affected (0.09 sec)
插入1234,这时候会提示数据越界:
mysql> insert into date_5 values(1234); ERROR 1264 (22003): Out of range value for column 'y' at row 1
插入正常范围内的数据:
mysql> insert into date_5 values(1999); Query OK, 1 row affected (0.02 sec) mysql> insert into date_5 values(2016); Query OK, 1 row affected (0.02 sec)
数据展示:
mysql> select * from date_5; +------+ | y | +------+ | 1999 | | 2016 | +------+ 2 rows in set (0.00 sec)
2.4 字符串类型
Char & varchar
CHAR和VARCHAR类型声明的长度表示你想要保存的最大字符数。
Char,定长字符串,保存时如果字符串长度不够,则后边补足空字符串;但是在读取到数据是,会截取后边所有的字符串。因此如果真实数据存在左边空格,则需要注意。
varchar,变长字符串。在保存字符串时,同时保存该字符串的长度,小于255采用一个字节保存,否则采用二个字节保存。不会像char一样截取空格。
在定义类型长度时,同时一条记录的总长度是 65535.因此所有字段的总长度不能超过改值。同时每条记录还需要一个字节保存是否有null值,如果都没有null(都不允许为null)则该字节省略。
枚举
ENUM('value1','value2',...)
枚举值应该在值列表内,允许使用下标方式标识。1标识第一个元素,逐个递增。
除此之外,允许null和空字符串(下标为0)
下标方式,可以使用在检索中。
集合
Set(‘value1’,’value2’,…);
表示可以选择可用值的0个或多个组合。
二进制类型:
如果需要保存一个二进制文件内容的话,应该保存成这些类型,例如图片内容。
2.4.1 char & varchar类型
char(M)表示固定长度;varchar(M)表示可变长度。
其中M表示允许的字符串的长度,M在varchar中的表示,是允许的最大长度;char内M表示严格限定的长度。
char(5) | varchar(5) | ||
‘’ | 5个字符 | 1个字符 | varchar需要一个字节保存字符串总长度 |
‘abc’ | 5 | 4 | |
‘abcde’ | 5 | 6 | |
存储格式取决于当前数据库的字符集:
utf8中一个字符占用三个字节21845*3 = 65536
gbk中一个字符占用两个字节32767*2 = 65534
常见一个最大长度字符表str_1:
mysql> create table if not exists str_1( -> `c` char(255) -> ); Query OK, 0 rows affected (0.07 sec)
创建一个最大(65535)的varchar数据类型表(失败):
mysql> create table if not exists str2( -> `c` varchar(65535) -> )character set latin1; ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to cha ge some columns to TEXT or BLOBs mysql>因为varchar类型除了还要保存额外总的字符个数,除了类型本身的限制之外,还有记录总的长度;
创建成功的最大实例(字符集latin1只占用一个字符):
mysql> create table if not exists str2( -> `c` varchar(65533) not null -> )character set latin1; Query OK, 0 rows affected (0.09 sec)
创建不成功(超过255个字符,就要用两个字节保存字符个数,且null也占用一个字符):
mysql> create table if not exists str3( -> `c` varchar(65533) -> )character set latin1; ERROR 1118 (42000): Row size too large. The m ge some columns to TEXT or BLOBs mysql>
创建成功:
mysql> create table if not exists str3( -> `c` varchar(65532) -> )character set latin1; Query OK, 0 rows affected (0.09 sec)
真是的varchar长度:
记录存在总长度 65535限制。
varchar特点,当 类型数据超过255个字符时,采用2个字节表示长度。
65535-2=65533
整条记录,需要一个额外的字节,用于保存当前字段的null值。
除非所有的字段都比不是nul,这个字节才可以省略。一个记录,不论有多少个字段
存在null,都是使用统一的一个字节来表示。而不是每个字段一个字节。
创建不成功,因为下边的tinyint也要占用一个null字节:
mysql> create table if not exists str4( -> `c` varchar(65533) not null, -> `i` tinyint -> )character set latin1; ERROR 1118 (42000): Row size too large. The maximum ge some columns to TEXT or BLOBs
2.4.2 test
能保存的长度2^16,总长度2^16+2,需要额外的两个字节文本,有很多 兄弟类型(不用指定长度)Tinytext longtext
表示的字符串长度不一样。
2.4.3 枚举(enum)
Enum,限制了当前的数据,看上去是一个字符串,其实保存的是整型(默认从1开始计数),最多允许有65535个枚举项,也就是2个字节(但是会有一些其他的消耗,最终不能达到65536长度创建枚举表enmu_1:
mysql> create table if not exists enum_1( -> `e` enum('female', 'male') -> ); Query OK, 0 rows affected (0.06 sec)
插入数据方式1:
mysql> insert into enum_1 values('female'); Query OK, 1 row affected (0.02 sec) mysql> insert into enum_1 values('male'); Query OK, 1 row affected (0.02 sec)
插入数据方式2:
mysql> insert into enum_1 values(2); Query OK, 1 row affected (0.02 sec) mysql> insert into enum_1 values(1); Query OK, 1 row affected (0.01 sec)
数据展示1:
mysql> select * from enum_1; +--------+ | e | +--------+ | female | | male | | male | | female | +--------+ 4 rows in set (0.00 sec)
数据展示2:
mysql> select e+0 from enum_1; +------+ | e+0 | +------+ | 1 | | 2 | | 2 | | 1 | +------+ 4 rows in set (0.00 sec)
2.4.4 set集合(相当于多项选择题)
创建set表:mysql> create table if not exists set_1( -> `s` set('A', 'B', 'C', 'D') -> ); Query OK, 0 rows affected (0.06 sec)
插入数据:
mysql> insert into set_1 values('A'); Query OK, 1 row affected (0.03 sec) mysql> insert into set_1 values('A,B'); Query OK, 1 row affected (0.02 sec) mysql> insert into set_1 values('C'); Query OK, 1 row affected (0.01 sec) mysql> insert into set_1 values('C,D'); Query OK, 1 row affected (0.01 sec)
数据展示1:
mysql> select * from set_1; +------+ | s | +------+ | A | | A,B | | C | | C,D | +------+
数据展示2:
mysql> select s+0 from set_1; +------+ | s+0 | +------+ | 1 | | 3 | | 4 | | 12 | +------+ 4 rows in set (0.00 sec)
数据展示2的分析:set总共占据8个字节,也就是64为二进制数字,列表中每个参数占据一位,也就是说最多保存64中状态。
上述参数中的二进制存储方式为(1,10,100,1000),所以会出现数据展示2中的情况。
总结:
应该使用最精确的类型。占用的空间少。
还应该考虑到相关应用语言的处理。例如常常将时间日期保存成一个整型。便于计算。
考虑移植的兼容性。
相关文章推荐
- MySQL快速入门04----数据类型
- 数据类型,运算符和表达式03 - 零基础入门学习C语言04
- 复杂的数据类型1 - C++快速入门07
- 21分钟 MySQL 入门教程 && mysql数据类型
- MySQL 入门 之 数据类型
- C++ Primer快速入门之四:变量和数据类型
- 数据类型,运算符和表达式04 - 零基础入门学习C语言05
- MYSQL入门学习之四:MYSQL的数据类型
- 快速入门C++ 03(复杂数据类型)
- mysql json类型快速入门
- 【转】MYSQL入门学习之四:MYSQL的数据类型
- 复杂的数据类型1 - C++快速入门07
- 复杂的数据类型3 - C++快速入门09
- MySQL入门12-数据类型
- J2EE入门视频教程第五讲——MySQL中的数据类型及命令行基本查询语句
- 复杂的数据类型3 - C++快速入门09
- 复杂的数据类型2 - C++快速入门08
- 复杂的数据类型4 - C++快速入门10
- Swift快速入门(二)基本数据类型
- Python学习笔记(二):语句、数据类型(快速入门篇)