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

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


总结:



  • 应该使用最精确的类型。占用的空间少。
  • 还应该考虑到相关应用语言的处理。例如常常将时间日期保存成一个整型。便于计算。
  • 考虑移植的兼容性。






























类型


  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值