您的位置:首页 > 数据库 > MySQL

MySQL快速入门04----数据类型

2017-04-08 15:29 513 查看


转自:http://lib.csdn.net/article/mysql/45961?knId=383


一 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’                54 
‘abcde’  56 
    
M表示的是字符数,而不是字节数。但是,总的长度的使用是按照 字节计算的。

存储格式取决于当前数据库的字符集:

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中的情况。


总结:



应该使用最精确的类型。占用的空间少。
还应该考虑到相关应用语言的处理。例如常常将时间日期保存成一个整型。便于计算。
考虑移植的兼容性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: