数值类型
int类型
int
类型包含以下五种:
类型 | 大小 |
---|---|
tinyint | 1 byte |
smallint | 2 byte |
mediumint | 3 byte |
int | 4 byte |
bigint | 8 byte |
表t1
的num
列的类型就是tinyint
,我们尝试对其插入数据,来测试其范围。tinynt
占1 byte
,那么就可以表示256
个数字。
成功插入了-1
,说明tinyint
默认是有符号的。其实整个int
家族,默认都是带符号的。
如果想要不带符号,建表时在类型的末尾后紧跟unsigned
:
当tinyint
有符号时,存储范围是[-128, 127]
;无符号时,范围是[0, 255]
。其它int
家族的成员同理。
bit类型
顾名思义,bit
类型就是自己指定比特位的数目。
语法:
bit(M)
其中M
表示比特位的数目,如果省略(M)
则默认表示一个比特位,M
的取值范围是[1, 64]
。
t3
表有两列,分别是id
和online
,online
的类型是bit(1)
(也可省略为bit
),即只占用一个比特位。
分别对online
插入0, 1, 2
,发现0
和1
可以正常插入,但是2
不行,因为一个比特只能表示0
和1
。bit类型在输出时,默认以ASCII
码的形式展示,而0
和1
在ASCII
码中是控制字符,不可输出,所以我们看不到。
我现在将bit(1)
改为bit(10)
,然后插入数字97
:
可以看到,最后数字97
输出时,输出的是97
对应的字符'a'
。
浮点类型
float / double
float
与double
用于存储浮点型,也就是小数,占用内存如下:
类型 | 大小 |
---|---|
float | 4 byte |
double | 8 byte |
语法:
float(m, d) [unsigned]
其中m
指定浮点数的总长度,d
指定小数位数。
float(4, 2)
,表示整个浮点数占4
位数字,小数点后占2
位,也说明了小数点前的数字位数是4 - 2 = 2
位,存储范围是[-99.99, 99.99]
。
如果希望存储无符号的数字,那么就是float(4, 2) unsigned
,但是与整数不同,unsigned
对浮点数只影响最小值为0
,最大值不变,此时存储范围变成[0, 99.99].
首先创建一张表,其中第二列num
的类型是float(4,2)
:
99.99
正常插入了,但是100
超出范围了,可见99.99
是边界值。
可知:当小数点后位数不足时,自动补0
到精度。
可知:当小数点后超出精度,此时发生四舍五入。
float
可以不指定(m, d)
,此时直接使用 float
不会强制保留固定数量的小数位,而是更具输入的数字实时调整。
- 直接使用
float
,数字的位数可以根据插入的值自由调整 - 对于精度较高的数字,无法很好的保存,会四舍五入
一般来说,float
的精度是7
位十进制数字,包括小数点前后。而456.78910
有8
位数字,所以发生了精度损失。
在插入较大的整数时,整数也会有损失,比如插入123456789
:
decimal
从刚刚的float
讲解可以看出:float
与double
会有精度损失,不适合存储对精度要求高的小数,因此MySQL推出了decimal
类型,专门用于存储高精度要求的浮点数。
语法:
decimal(m,d) [unsigned]
decimal
最大的m
为65
,最大的d
为30
。如果省略m
,则默认m=0
,如果省略d
,则默认d=10
。
在使用上,decimal
与float / double
没有任何区别。
字符串类型
MySQL
中,字符串使用了char
和varchar
来存储,与大部分编程语言不同,编程语言中char
往往只存储一个字符。
char
char
用于存储固定长度的字符串。
语法:
char(L)
L
用于指定字符串的最大长度,L
的最大值为255
。
字符串'a'
,'ab'
,'abc'
都插入成功了,而'abcd'
超出了长度,插入失败。
字符串'中国人'
插入成功了,根据utf8
编码规则,普通字母占1 byte
,而汉字占3 byte
。在部分编程语言中,例如C/C++
,汉字算作三个字符,但是MySQL
中认为一个汉字也是一个字符!
varchar
语法:
varchar(L)
L
用于指定字符串的最大长度,L
的最大值为不确定,但是最大字节数为65535
。
对于char
来说,如果指定了字符串的长度,那么存入的所有字符串都是这个长度所占字节的大小。对于varchar
来说,只要存入的字符串没有超过指定长度,那么该字符串占用多少内存,就实际开辟多少内存!
经过计算,若以utf8
编码,varchar
最大能存储65535 / 3 = 21845
个字符。
BUT,因为varchar类型每个字符串占用的字节数不确定,所以读取内存时,不知道这个字符串读取到啥时候结束,所以在整个字符串的首部,需要开辟1 - 3 byte,来存储这个字符串的长度。总共有65535 byte,减去首部占用的3 byte,最后能用的只有(65535 - 3) / 3 = 21844个字符.
日期时间类型
在MySQL
中,日期与时间也有专门的类型来存储,包以下三种:
类型 | 含义 | 格式 | 大小 |
---|---|---|---|
data | 日期 | yyyy-mm-dd | 4 byte |
datetime | 日期 + 时间 | yyyy-mm-dd HH:ii:ss | 8 byte |
timestamp | 时间戳 | yyyy-mm-dd HH:ii:ss | 4 byte |
通过desc
可以看到,timestamp
的默认值Default
为CURRENT_TIMESTAMP
,也就是当前的时间。
time1
和time2
都按照正常格式插入了,与之同时time3
自动更新为了当前时间。一般来说timestamp
与datetime
没有格式上的区别,但是由于timestamp
会自动更新,所以一般用于保存最后一次的修改时间.
enum & set
enum
为枚举类型,用于进行单选。
语法:
enum('选项1', '选项2', '选项3', ...)
set
为集合类型,用于进行多选。
语法:
set('选项1', '选项2', '选项3', ...)
现在创建了表t10
,其第二列gender
为枚举enum
,第三列hobby
为集合set
。通过desc
可知,enum
和set
都允许为NULL
张三
有多个爱好,此时多个选项用逗号隔开:'篮球,羽毛球'
。
那么对于enum
和set
来说,它们底层都使用数字来存储。
- 在
enum
中,选项从前往后分别用数字1,2,3,4,5...
表示,最大值为65535
- 在
set
中,选项通过位图存储,第一个选项为二进制1
,第二个选项为二进制10
,第三个选项为二进制100
,以此类推,最多64
个选项
比如enum('男','女','保密')中,'男' = 1,'女' = 2,'保密' = 3;set('羽毛球','乒乓球','篮球','足球') 中,'羽毛球' = 1,'乒乓球' = 2,'篮球' = 4,'足球' = 8。
在插入时,如果想选中'羽毛球,足球',就可以插入8+1=9.
对于set
,多选包括不选,插入空字符串''
,或者数字0
都可: 此处要注意,空串表示啥也不选,此处表示这个人没有任何爱好。而NULL
表示缺少这个值,此处表示这个人的爱好不确定