标签:MySQL入门程序员
咱们前边说过,MySQL
底层其实把数据存储到了表里边,而表又是由行和列组成的,仍是拿咱们以前说过的学生基本信息表
作个例子:数据库
学号 | 姓名 | 性别 | 身份证号 | 学院 | 专业 | 入学时间 |
---|---|---|---|---|---|---|
20180101 | 杜子腾 | 男 | 158177199901044792 | 计算机学院 | 计算机科学与工程 | 2018-09-01 |
20180102 | 杜琦燕 | 女 | 151008199801178529 | 计算机学院 | 计算机科学与工程 | 2018-09-01 |
20180103 | 范统 | 男 | 17156319980116959X | 计算机学院 | 软件工程 | 2018-09-01 |
20180104 | 史珍香 | 女 | 141992199701078600 | 计算机学院 | 软件工程 | 2018-09-01 |
20180105 | 范剑 | 男 | 181048200008156368 | 航天学院 | 飞行器设计 | 2018-09-01 |
20180106 | 朱逸群 | 男 | 197995199801078445 | 航海学院 | 电子信息 | 2018-09-01 |
表里的一行就表明一个学生的基本信息,这一行中的某一列就表明这个学生基本信息中的一项属性,也就是说学号
是学生的一项属性、姓名
也是学生的一项属性,其余的列也都是这个学生的属性。可是这些属性都有必定格式,好比说学号必须是整数格式的,入学时间必须是日期格式的,其余的属性都是字符串格式的,不一样格式的数据是不能随便乱填的,你把一个日期格式的数据填在了性别里,岂不是闹出了笑话。因此设计MySQL
的大叔们针对每一种格式定义了一种相应的类型,咱们接下来就要详细唠叨具体有哪些类型以及它们是怎么存储在计算机中的。bash
注:身份证号因为最后觉得多是X,因此就归为字符串了。 性能
long long ago,原始人是没有如今的人这么聪明的,只会用十分简单的东西计数。比方说他们只会使用麦秆来统计猎物数量,每收获一个猎物就在麦秆堆里添加一支麦秆,因此若是猎物多的话,麦秆就会累积不少,数都数不过来。后来人们发现不用这么笨,能够把麦秆折叠成不一样的形状来表明不一样的数量。普通的麦秆就表明1,也就是说每添加一只猎物就多放一只普通麦秆;若是当前已经放了9根普通的麦秆,此时再添加了一只猎物,就用一个心形麦秆来取代以前的9根普通麦秆;假如当前已经有了9根心形麦秆和9根普通麦秆时又添加了一只猎物的话,就用一根矩形麦秆来替代以前全部的麦秆。像这种每逢10个数向前进一位的计数方法就叫作十进制,这样他们就能够用不多的麦秆来表示很大的数字了。学习
若是在计数的时候每逢8个数就往前进一位就是八进制,每逢9个数就往前进一位就是九进制。生活中经常使用的进制除了十进制外,还有钟表里用来统计时间的十二进制和六十进制,用在计算机里的二进制和十六进制。 以十进制数字109
为例,它表示有1个10²
,加0个10¹
,加9个10⁰
,用数学符号表示就是:优化
109 = 1 × 10² + 0 × 10¹ + 9 × 10⁰
复制代码
这个数字也能够这么表示:编码
109 = 1 × 8² + 5 × 8¹ + 5 × 8⁰
复制代码
也就是从八进制的逢8进一的角度上考虑,这个数能够被表示为155
(八进制)。固然这个数也能够这么写:spa
209 = 1 × 2⁶ + 1 × 2⁵ + 0 × 2⁴ + 1 × 2³ + 1 × 2² + 0 × 2¹ + 1 × 2⁰
复制代码
也就是从二进制的逢2进一的角度上考虑,这个数也能够被表示为:1101101
(二进制)。又由于计算机中通常用8个位表示一个字节,平时都是用若干个字节来表示一个整数,假如用1个字节表示109
的话,那效果就是这样:01101101
,假如用两个字节表示十进制数19
的话,那效果就是这样:0000000001101101
。操作系统
很显然,使用的字节数越多,意味着能表示的数值范围就越大,可是也就越耗费存储空间。根据表示一个数占用字节数的不一样,MySQL
把整数划分红以下所示的类型:设计
类型 | 字节数 | 无符号数取值范围 | 有符号数取值范围 | 含义 |
---|---|---|---|---|
TINYINT |
1 | 0 ~ 2⁸-1 | -2⁷ ~ 2⁷-1 | 很是小的整数 |
SMALLINT |
2 | 0 ~ 2¹⁶-1 | -2¹⁶ ~ 2¹⁶-1 | 小的整数 |
MEDIUMINT |
3 | 0 ~ 2²⁴-1 | -2²⁴ ~ 2²⁴-1 | 中等大小的整数 |
INT |
4 | 0 ~ 2³²-1 | -2³² ~ 2³²-1 | 标准的整数 |
BIGINT |
8 | 0 ~ 2⁶⁴-1 | -2⁶⁴ ~ 2⁶⁴-1 | 大整数 |
以TINYINT
为例,用1个字节,也就是8个位表示有符号数
的话,就是既能够表示正数,也能够表示负数的话,须要有一个二进制位表示正负号。可是若是表示无符号数
的话,也就是只表示非负数的话,就不须要表示正负号,这是有符号数
和无符号数
的区别。具体每一个类型的取值范围是如何计算出来的咱们这就不唠叨了,能够找一本计算机基础的书看看。
浮点数就是小数,咱们平时用的的十进制小数也能够被转换成二进制后被计算机存储。好比9.875
,这个小数能够被表示成这样:
9.875 = 8 + 1 + 0.5 + 0.25 + 0.125 = 1 × 2³ + 1 × 2⁰ + 1 × 2⁻¹ + 1 × 2⁻² + 1 × 2⁻³
复制代码
也就是说,若是十进制小数9.875
转换成二进制小数的话就是:1001.111
。为了在计算机里存储这种二进制小数,咱们统一把它们表示成a × 2ⁿ
的科学计数法的形式,其中1≤|a|
<2,好比1001.111
能够被表示成1.001111 × 2³
,咱们把小数点以后的001111
称为尾数
,把2³
中的3
称为指数
,而后只须要在计算机中的二进制位中表示出尾数
和指数
就好了。用科学技术法来计数的时候,小数的小数点看起来就像移动了同样,因此这样的小数也叫作浮点数
。
固然,若是你须要表示有符号小数
,那还得用一个二进制位来表示正负号。若是咱们用四个字节,也就是32个位来表示一个有符号小数的话,咱们能够这么划分各个部分所表示的意义:
很显然,使用的字节数越多,表示尾数
和指数
的范围就越大,也就是说表示的小数范围就越大,因此设计MySQL
的大叔根据表示一个小数须要的不一样字节数定义了以下的两种类型来表示小数:
类型 | 字节数 | 绝对值最小非0值 | 绝对值最大非0值 | 含义 |
---|---|---|---|---|
FLOAT |
4 | ±1.175494351e-38 | ±3.402823466e38 | 单精度浮点数 |
DOUBLE |
8 | ±2.2250738585072014e-308 | ±1.7976931348623157e308 | 双精度浮点数 |
须要注意的是,虽然有的十进制小数,好比1.875
能够被很容易的转换成二进制数0.111
,可是更多的小数是没法直接转换成二进制的,好比说0.3
,它转换成的二进制小数就是一个无限小数,可是咱们如今只能用4个字节或者8个字节来表示这个小数,因此只能进行四舍五入来近似的表示,因此咱们说计算机的浮点数表示有时是不精确的。
对于咱们用户而言,使用的都是十进制小数。表示一个小数须要的数字个数称为有效位数
,小数点后的数字个数称为小数位数
,11.2
和-0.0021
这两个小数的有效位数和小数位数见下表:
小数 | 有效位数 | 小数位数 |
---|---|---|
11.2 |
3 | 1 |
-0.0021 |
5 | 4 |
若是咱们知道某列属性须要的有效位数和小数位数,咱们能够用这样的方式手动指定一下:
FLOAT(M, D) 或 DOUBLE(M, D),其中M指`有效位数`,D指`小数位数`
复制代码
举个例子看一下,设置了有效位数和小数位数的单精度浮点数的取值范围的变化:
类型 | 取值范围 |
---|---|
FLOAT(4, 1) |
-999.9~999.9 |
FLOAT(5, 1) |
-9999.9~9999.9 |
FLOAT(6, 1) |
-99999.9~99999.9 |
FLOAT(4, 0) |
-9999~9999 |
FLOAT(4, 1) |
-999.9~999.9 |
FLOAT(4, 2) |
-99.99~90.99 |
能够看到,在小数位数相同的状况下,有效位数越多,该类型的取值范围越大;在有效位数相同的状况下,小数位数越大,该类型的取值范围越小。固然,M
和D
的取值也不是无限大的,你要是把有效位数取成一个亿,那内存不得崩了么,别忘了单精度浮点数只有4个字节的存储空间,双精度浮点数只有8个字节的存储空间,超过了这个存储空间所能表达的小数就无效了。
正由于用浮点数表示小数可能会有不精确的状况,在一些状况下咱们必须保证小数是精确的,因此设计MySQL
的大叔们提出了定点数的概念,它也是存储小数的一种方式:
类型 | 字节数 | 取值范围 |
---|---|---|
DECIMAL(M, D) |
取决于M和D | 取决于M和D |
此处的M
指的就是有效位数,D
指的就是小数位数。M
和D
对取值范围的影响咱们以前在唠叨浮点数的时候已经介绍过了,可是为啥M
和D
的取值还会影响到须要的字节数呢?
咱们说定点数是一种精确的小数,为了达到精确的目的咱们不能把它转换成二进制以后再存储(这可能会产生四舍五入的状况)。咱们能够以小数点为界,把一个小数当作是两个整数被小数点分隔开来的样子,因此咱们能够把一个小数分红3块来存储,一是小数点左边的整数,而是小数点自己,三是小数点右边的整数,这样就能够保证存储的小数确定是精确的了。
以DECIMAL(6, 1)
为例,这种类型的取值范围是-99999.9~99999.9
。因此整数部分绝对值最大的就是99999
,小数部分最大的就是9
,而整数部分的最大值99999
这个十进制数最少须要用3个字节才能存放,小数部分的最大值9
只须要1个字节就能够存放,因此最后这个定点数类型就须要使用5个字节,各个部分的划分以下:
因此不一样的有效位数和小数位数,最终须要的字节数也是不一样的。能够看到,与浮点数相比,定点数须要更多的空间来存储数据,因此若是不是像工资同样特重要的数据,通常的小数用浮点数就足够了。
M
和D
都是可选的,默认的M
的值是10,默认的D
的值是0,也就是说下列等式是成立的:
DECIMAL = DECIMAL(10) = DECIMAL(10, 0)
DECIMAL(n) = DECIMAL(n, 0)
复制代码
另外,有效位数和小数位数也不是无限大的(太大了内存受不了),限制M
的范围是1~65
,D
的范围是0~30
,且D
的值不能超过M
。
对于数值类型,包括整数、浮点数和定点数,有些状况下咱们只须要用到非负数,并且对于整数来讲,单纯的表示非负数能将正整数的表示范围提高一倍,因此MySQL
给咱们提供了一个表示非负数值类型的方式,就是在原数值类型后加一个单词UNSIGNED
:
数值类型 UNSIGNED
复制代码
你们能够把它当成一种新类型对待,好比INT UNSIGNED
就表示非负整数,取值范围是0 ~ 2³²-1
。
字符
分为两种,一种叫可见字符
,一种叫不可见字符
。顾名思义,可见字符
就是打印出来后能看见的字符。好比a
,b
,我
,。
... 这样的人眼能看见的单个国家文字、标点符号、图形符号、数字等这样的东东,咱们就叫作一个可见字符
。不可见字符
也好理解,就是打印机或者在黑框框里打印字符的时候有时候须要换行,打个制表符啥的,或者在输出某个字符的时候就发出嘟
地一声,这种咱们看不到,只是为了控制输出效果的字符叫作不可见字符
。字符串
就是把字符连起来的样子,好比abc
,就是由a
、b
、c
三个字符连起来的一个字符串
,下边列举了4个字符串的例子:
'我喜欢你'
'me, too'
'give me a hug'
'么么哒'
复制代码
在具体分析MySQL
中各个字符串类型以前,咱们必定要先搞明白字符和字节的区别。字符是面向人的概念,字节是面向计算机的概念。若是你想在计算机中表示字符,那就须要经过字符编码
来将一个字符映射到一个二进制数据。不幸的是,这种映射关系并非惟一的,不一样的人制做了不一样的字符编码,根据表示一个字符使用的字节数是否是相同的,编码方式能够分为下边两种:
固定长度的编码
采用相同的字节数来表示一个字符,比方说ASCII
编码方式采用1个字节来表示一个字符,ucs2
采用2个字节来表示一个字符。
变长编码 采用长度不同的字节来表示不一样的字符,比方说utf8
编码方式采用1~3
个字节来编码一个字符,gb2312
采用1~2
个字节来编码一个字符。
对于不一样的字符编码方式来讲,对一样一个字符可能会产生不同的编码,好比一样一个字符:我
,在utf8
和gb2312
这两种编码方式下被映射成以下的二进制数据以下:
`utf8`编码:111001101000100010010001 (3个字节,十六进制表示是:0xE68891)
`gb2312`编码:1100111011010010 (2个字节,十六进制表示是:0xCED2)
注:十六进制前边的`0x`是前缀,表示后边的是16进制数据。
复制代码
若是你对上边说的话只知其一;不知其二,那你须要系统的学习一下字符集的相关概念:字符集和编码介绍。
小贴士: MySQL对`utf8`编码作了限制,它只能使用3个字节去编码字符,若是有的字符须要4个字节的话,可使用`utfmb4`,这只是出于性能考虑的,毕竟咱们的大部分场景中不会使用到4个字节编码的字符。
如今咱们能够看一下MySQL
中提供的各类字符串类型(注:其中M
表明你要存储的字符串中最多包含的字符数量,L
表明在实际字符串在某个字符编码下所占用的字节数,W
表明某个固定长度编码方式中编码一个字符须要的字节数):
类型 | 最大长度 | 存储空间要求 | 含义 |
---|---|---|---|
CHAR(M) |
M个字符 | L个字节或M个字节或M×W个字节 | 固定长度的字符串 |
VARCHAR(M) |
M个字符 | L+1 或 L+2 个字节 | 可变长度的字符串 |
TINYTEXT |
2⁸-1 个字节 | L+1个字节 | 很是小型的字符串 |
TEXT |
2¹⁶-1 个字节 | L+2 个字节 | 小型的字符串 |
MEDIUMTEXT |
2²⁴-1 个字节 | L+3个字节 | 中等大小的字符串 |
LONGTEXT |
2³²-1 个字节 | L+4个字节 | 大型的字符串 |
CHAR(M)
中的M
取值范围是0~255
。若是省略掉M
的值,那它的默认值就是1,也就是说CHAR
和CHAR(1)
是一个意思。再回头看一眼咱们的学生基本信息表,若是你以为学生的姓名不会超过5个字符,你就能够指定这个姓名列的类型为CHAR(5)
。
CHAR(M)
在不一样的编码方式下须要的存储空间也是不同的。假设咱们实际存储的字符串在某个编码方式下占用的字节数为L
,则CHAR(M)
实际占用的字节数取决于该编码方式是不是固定长度的以及M
和L
的值,具体计算方式以下:
若是该编码方式是固定长度的,W
表明固定长度的字节数,比方说ASCII
编码方式的W
的值就是1
,ucs2
编码方式的W
的值就是2
,则CHAR(M)
占用的存储空间大小与实际存储的数据无关,都是M×W
个字节。
若是该编码方式是变长的,则分为两种状况:
若是L
小于M
,则占用的存储空间大小为M
个字节。
若是L
大于M
,则占用的存储空间大小为L
个字节。
比方说咱们如今使用的字符串类型为CHAR(5)
,因此如今M
的值就是5
,而后咱们看一下CHAR(5)
实际占用的存储空间的状况:
若是咱们使用固定长度编码ucs2
进行编码,无论存储的数据是啥,最后占用的存储空间都同样。
W
的值是2,因此CHAR(5)
占用的空间就是5×2=10
个字节。
若是咱们使用变长的utf8
进行编码。
假设实际存储的字符串为我
,由于它用utf8
编码后的结果是0xE68891
,也就是说实际占用空间L
的值为3
,又由于L < M
,因此实际占用的存储空间大小为5
个字节。
假设实际存储的字符串为我我
,由于它用utf8
编码后的结果是0xE68891E68891
,也就是说实际占用空间L
的值为6
,又由于L > M
,因此实际占用的存储空间大小为6
个字节。
小贴士: 能够看到,`CHAR(M)`只有在采用固定长度的字符编码时所占用的存储空间大小才是肯定的,不然占用存储空间大小与实际字符串占用的字节长度有关。
须要注意的是:若是CHAR(M)
占用的存储空间大于实际字符串须要的存储空间,那多出的存储空间将被空格
填满。这种CHAR(M)
的字符串类型有一个很是很差的地方:一旦你肯定了M
的值,若是M
的值很大,而你实际存储的字符串占用字节数又不多,会形成存储空间的浪费。
若是你表中的某个列须要存储字符串类型的数据,并且这些字符串长短不一,那么使用CHAR(M)
可能形成很大程度上的浪费,VARCHAR(M)
正是为了解决这个问题而生的。
VARCHAR(M)
中的M
也是指你要存储的字符串中最多包含的字符数量,取值范围是1~65535
。可是MySQL
中还有一个规定,就是某一行包含的全部列中存储的数据大小不得超过65535个字节,因此VARCHAR(M)
实际可以容纳的字符数量确定小于65535。
一个VARCHAR(M)
类型表示的数据由这么两部分组成:
真正的字符串内容。
占用字节数。
假设真正的字符串内容编码后占用字节数为L
,若是L
不大于255,也就是字节数能够用1个字节来表示,那么实际占用的存储空间就是L+1
个字节;若是L
大于255且不大于65535,也就是字节数能够用2个字节来表示,那么实际占用的存储空间就是L+2
个字节;又由于某一行包含的全部列中存储的数据大小不得超过65535个字节,因此L
不可能大于65535。因此实际占用的存储空间只多是L+1
个字节或者L+2
个字节。
咱们还用学生的姓名属性作例子,在使用utf8
编码方式的状况下,杜子腾
和范统
这两个字符串能够被编码成以下的样子(二进制太长了,用16进制表示):
`杜子腾`:0xE69D9CE5AD90E885BE (共9个字节)
`范统`:0xE88C83E7BB9F (共6个字节)
复制代码
假设咱们给姓名列定义的类型为VARCHAR(5)
,咱们看一下这两个字符串的实际存储示意图:
从这个图例也能够看出了,VARCHAR(M)
占用的存储空间大小随着实际存储的内容变化而变化,因此咱们说 VARCHAR(M) 是一种可变长度的字符串类型。
虽然VARCHAR(M)
已经能够存储很长的字符串了,但是仍是不够咋办?对于很长的字符串,设计MySQL
的大叔们给咱们提供了TINYTEXT
、TEXT
、MEDIUMTEXT
、LONGTEXT
四种能够存储大型的字符串的类型。它们也都是变长类型,由实际内容和内容长度构成,由于TINYTEXT
最多能够存储2⁸-1
个字节,因此内容长度用1个字节就能够表示,TEXT
最多能够存储2¹⁶-1
个字节,因此内容长度用2个字节就能够表示,剩下的两个的内容长度占用的字节数也都是按这个规则算出来的。
不是以前有个规定说某一行包含的全部列中存储的数据大小不得超过65535个字节么?那TEXT
、MEDIUMTEXT
、LONGTEXT
这3个类型岂不是不符合规定喽?哈,因为MySQL
的大叔会特别关照这几种类型,因此这几个类型并不在这个规定的限制范围以内。你们若是有什么特别长的文本就能够考虑使用这几个类型了。
视角回到咱们的学生信息表,性别一列也须要填写字符串,可是比较特殊的一点是,这一列只能填男
或者女
,填别的字符串就尴尬了!针对这种状况,咱们提出了一个叫ENUM
的类型,也称为枚举类型
,它的格式以下:
ENUM('str1', 'str2', 'str3' ⋯)
复制代码
它表示在给定的字符串列表里选择一个。好比咱们的性别一列能够定义成ENUM('男', '女')
类型。这个的意思就是性别一列只能在'男'
或者'女'
这两个字符串之间选择一个,至关于一个单选框~
有的时候某一列的值能够在给定的字符串列表中挑选多个,假设学生的基本信息加了一列兴趣
属性,这个属性的值能够从给定的兴趣列表中挑选多个,那咱们可使用SET
类型,它的格式以下:
SET('str1', 'str2', 'str3' ⋯)
复制代码
它表示能够在给定的字符串列表里选择多个。咱们的兴趣一列就能够定义成SET('打球', '画画', '扯犊子', '玩游戏')
类型。这个的意思就是兴趣一列能够在给定的这几个字符串中选择一个或多个,至关于一个多选框~效果就像这样:
学号 | 姓名 | ··· | 兴趣 |
---|---|---|---|
20180101 | 杜子腾 | ··· | '打球', '画画' |
20180102 | 杜琦燕 | ··· | '扯犊子' |
20180103 | 范统 | ··· | '扯犊子', '玩游戏' |
20180104 | 史珍香 | ··· | '画画', '扯犊子', '玩游戏' |
ENUM 和 SET 都是一种特殊的字符串类型,在从字符串列表中单选或多选元素的时候用获得它们。
咱们有不少场景须要表示时间或日期,好比学生基本信息中的入学时间
就须要用日期的格式保存。MySQL
为咱们提供了多种关于时间和日期的类型,各类类型能表示的范围以下:
类型 | 存储空间要求 | 取值范围 | 含义 |
---|---|---|---|
YEAR |
1字节 | 1901~2155 | 年份值 |
DATE |
3字节 | '1000-01-01' ~ '9999-12-31' | 日期值 |
TIME |
3字节 | '-838:59:59' ~ '838:59:59' | 时间值 |
DATETIME |
8字节 | '1000-01-01 00:00:00' ~ '9999-12-31 23:59:59' | 日期加时间值 |
TIMESTAMP |
4字节 | '1970-01-01 00:00:01' ~ '2038-01-19 03:14:07' | 时间戳 |
在MySQL5.6.4
这个版本以后,TIME
、DATETIME
、TIMESTAMP
这几种类型添加了对毫秒、微妙的支持。因为毫秒、微秒都不到1秒,因此也被称为小数秒
,MySQL
最多支持6位小数秒的精度,各个位表明的意思以下:
咱们能够选择TIME
、DATETIME
、TIMESTAMP
这几种类型最多支持到小数点后几位的时间精度,通用格式为:
类型(小数秒位数)
其中的`小数秒位数`能够在0、一、二、三、四、五、6中选择
复制代码
好比DATETIME(0)
表示精确到秒,DATETIME(3)
表示精确到毫秒,DATETIME(5)
表示精确到10微秒。若是你在选择TIME
、DATETIME
、TIMESTAMP
这几种类型的时候添加了对小数秒的支持,那么存储空间须要相应的扩大,不一样的小数秒精度须要的存储空间不一样,以下表:
小数秒精度 | 存储空间要求 |
---|---|
0 | 0字节 |
1或2 | 1字节 |
3或4 | 2字节 |
5或6 | 3字节 |
也就是说若是你选择使用DATETIME(1)
,那么须要的存储空间就是在DATETIME
的空间上再加上小数秒须要的空间,就是8+1=9
个字节,相似的,DATETIME(3)
就须要10个字节。因此,MySQL5.6.4
这个版本以后的各个类型须要的存储空间和取值范围就以下:
类型 | 存储空间要求 | 取值范围 | 含义 |
---|---|---|---|
YEAR |
1字节 | 1901~2155 | 年份值 |
DATE |
3字节 | '1000-01-01' ~ '9999-12-31' | 日期值 |
TIME |
3字节+小数秒的存储空间 | '-838:59:59[.000000]' ~ '838:59:59[.000000]' | 时间值 |
DATETIME |
8字节+小数秒的存储空间 | '1000-01-01 00:00:00[.000000]' ~ '9999-12-31 23:59:59'[.999999] | 日期加时间值 |
TIMESTAMP |
4字节+小数秒的存储空间 | '1970-01-01 00:00:01[.000000]' ~ '2038-01-19 03:14:07'[.999999] | 时间戳 |
固然,若是你使用的MySQL
版本还没到5.6.4
,那就不支持小数秒,能够翻上去看原来的存储空间和取值范围。下边咱们来详细看一下各类类型。
单纯的表示一个年份值而已~不过它只有1个字节大小,因此存储的年份值范围有限,若是咱们想存储更多的年份值,能够考虑更换成SMALLINT
(2字节)或者字符串类型啥的~
顾名思义,DATE
表示日期,格式是CCYY-MM-DD
;TIME
表示时间,格式是hh:mm:ss[.uuuuuu]
,DATETIME
表示日期+时间,格式是CCYY-MM-DD hh:mm:ss[.uuuuuu]
。其中的CC
、YY
、MM
、DD
、hh
、mm
、ss
、uuuuuu
分别表示世纪、年、月、日、时、分、秒、小数秒。
须要注意的是,DATETIME 中的时间部分表示的是一天内的时间,而 TIME 表示的是一段时间,并且能够表示负值。
1970-01-01 00:00:00
注定是一个特殊的时刻,这一天被称为位零日
,也称为纪元
,MySQL
中把某个时刻距离1970-01-01 00:00:00
的秒数称为时间戳
。比方说当前时间是2018-01-24 11:39:21
,距离1970-01-01 00:00:00
的秒数为1516765161
,那么2018-01-24 11:39:21
这个时刻的时间戳就是1516765161
。不过在MySQL5.6.4
以后,时间戳的值也能够加入小数秒。
用时间戳存储时间的好处就是,它展现的值能够随着时区的变化而变化。比方说咱们把2018-01-24 11:39:21
这个时刻存储到一个TIMESTAMP
的列中,那么在中国你看到的时间就是2018-01-24 11:39:21
,若是你去了日本,他们哪里的使用的是东京时间,比北京时间早一个小时,因此他们那显示的就是2018-01-24 10:39:21
。而若是你用DATETIME
存储2018-01-24 11:39:21
的话,那不一样时区看到的时间值都是同样的。
MySQL中有设置时区的方式,咱们这里先不唠叨,等用到的时候再说啊
复制代码
若是你是专业的程序员的话,确定对二进制数据不陌生,有时咱们也有存储这些二进制数据的需求。MySQL
提供了下边这些数据类型供咱们使用:
类型 | 最大长度 | 存储空间要求 | 含义 |
---|---|---|---|
BIT(M) |
M个位 | (M+7)/8个字节 | 固定长度的字符串 |
BINARY(M) |
M个字节 | M个字节 | 固定长度的字符串 |
VARBINARY(M) |
M个字节 | L+1 或 L+2 个字节 | 可变长度的字符串 |
TINYBLOB |
2⁸-1 个字节 | L+1个字节 | 很是小型的字符串 |
BLOB |
2¹⁶-1 个字节 | L+2个字节 | 小型的字符串 |
MEDIUMBLOB |
2²⁴-1 个字节 | L+3个字节 | 中等大小的字符串 |
LONGBLOB |
2³²-1 个字节 | L+4个字节 | 大型的字符串 |
对于BIT(M)
来讲,M
指的是该类型最多能存储的二进制位的个数,好比BIT(3)
就是指最多能存放3个二进制位。而内存空间最少的分配单位就是字节,因此不足一字节的按一字节计算,因此存储空间就是(M+7)/8个字节。
BINARY(M)
和VARBINARY(M)
对应于咱们前边提到的CHAR(M)
和VARCHAR(M)
,都是前者是固定长度的类型,后者是可变长度的类型,只不过BINARY(M)
和VARBINARY(M)
是用来存放字节的,而CHAR(M)
和VARCHAR(M)
是用来存储字符的。
TINYBLOB
、BLOB
、MEDIUMBLOB
、LONGBLOB
是针对数据量很大的二进制数据提出的,好比图片、音频、压缩文件啥的。它们很像TINYTEXT
、TEXT
、MEDIUMTEXT
、LONGTEXT
,不过BLOB
是用来存储字节的,而TEXT
是用来存储字符的而已。在一般状况下,咱们通常都是只存储个文件路径而已,而后使用操做系统的文件系统去访问文件的~
数据库底层使用表来存放数据的,一张表有不少列,每一个列都有可能存放不一样格式的数据,不一样格式的数据是不能混用的,因此MySQL
提出了许多类型来存储不一样格式的数据。
用来存储整数的类型有TINYINT
、SMALLINT
、MEDIUMINT
、INT
、BIGINT
这几种,它们须要的存储空间不一样,因此能表示的整数范围也不一样。
用来存储小数的有FLOAT
、DOUBLE
、DECIMAL
类型,前两个属于浮点型,后一个属于定点型,浮点型更省存储空间,而定点型更精确,这些表示小数的类型均可以使用(M, D)来指定小数的有效位数和小数位数。
用来存储字符串的有CHAR(M)
、VARCHAR
、TEXT
、MEDIUMTEXT
、LONGTEXT
这几种,它们实际占用的字节存储空间依赖与咱们当前使用的字符编码,由于在不一样编码下,同一个字符可能被编码成不一样长度的字节数据,其中的CHAR(M)
是固定长度的类型,其他集中都是可变长度的类型,真实长度取决于实际的字符串长度。
用来存储时间的有YEAR
、DATE
、TIME
、DATETIME
、TIMESTAMP
这几种类型,须要注意的是,在在MySQL5.6.4
这个版本以后,TIME
、DATETIME
、TIMESTAMP
这几种类型添加了对小数秒的支持,可是存储小数秒又要使用额外的存储空间。另外,TIMESTAMP
这种类型存储的是自1970-01-01 00:00:00
时刻起的秒数,因此在不一样时区下会显示不一样的时间值。
用来存储二进制数据的有BIT(M)
、BINARY(M)
、VARBINARY(M)
、TINYBLOB
、BLOB
、MEDIUMBLOB
、LONGBLOB
这几种,除了BIT(M)
是以二进制位为单位的之外,其他的类型都是以字节为单位的,而且它们的使用相似字符串中的各类类型,只不过一个是以字符为单位,一个以字节为单位而已~
本系列专栏都是MySQL入门知识,想看进阶知识能够到小册中查看:MySQL是怎样运行的连接 。小册的内容主要是从小白的角度出发,用比较通俗的语言讲解关于MySQL内核的一些核心概念,好比记录、索引、页面、表空间、查询优化、事务和锁等,总共的字数大约是三四十万字,配有上百幅原创插图。主要是想下降普通程序员学习MySQL内核的难度,让学习曲线更平滑一点~