文章目录
- 一、理解数据本身就是一种约束
- 1.tinyint类型和 tinyint unsigned类型
- 2.其他的int类型
- 二、bit类型
- 三、float类型
- 1.signed版本
- 注意
- 2.unsigned版本
- 四、decimal类型
- float 和 decimal 总结
- 五、char类型(固定长度)
- 六、varchar类型(可变长度)
- 总结
- char和varchar比较
- 七、日期和时间类型
- 八、enum和set类型
- enum
- set
- 总结
- enum和set的类型查找
一、理解数据本身就是一种约束
1.tinyint类型和 tinyint unsigned类型
先创建表t1
create table if not exises t1(
num tinyint
);
表中只有一个字段tinyint
向num字段中添加数据:
insert into t1 values(-1);
…
然而,当我们插入256时:
出现了错误
意味着数据库不允许我们插入不合法数据。
反之,插入的一定是合法的数据!!!
所以一般而言,数据本身就是一种约束!!!
约束程序员,尽可能正确地插入数据。
就算你不是一个很好的程序员,Mysql也能保证数据的合法性。
2.其他的int类型
二、bit类型
创建一个表时,如下:
向表中插入一些数据后,如下:
问题是:为什么online字段没有任何显示呢?
只需执行如下命令就能显示了:
select id , hex(online) from t1;
(以十进制的方式显示)
同时也可以修改online字段的大小:
alter table t1 modify online bit(10);
三、float类型
1.signed版本
比如salary float(4,2);
表示允许承装的最多位数是4位(总长度,包含整数部分和小数部分),小数点后最多占两位。
那插入的salary(工资)最大就是:99.99
由于在建表时,salary类型没有设置成unsigned类型,所以可以插入负数,但实际生活中没有负数的工资吧。。。
注意
小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。
比如要插入一个数:
insert into t2(id ,salary) values(1,99,991);
是会插入成功的,因为在小数点部分,会进行四舍五入,将1舍去。
但是当插入下面的数据时,就不行:
insert into t2(id, slary) values(2,99.996);
因为一旦最后一个小数位进位后,数据就超出了-99.99~99.99的范围。
2.unsigned版本
如果把float设置成unsigned版本,那么取值范围就相当于把负数部分直接丢掉。
比如:定义一个表时,把float设置成float(4,2) unsigned
那取值范围就是:0~99.99
总结:1.一般情况下,默认的float,不指定位数的情况下,可容纳数据位数是比较大的,跟不同的平台设计也有关。
2.有一些情况,存储的浮点数类型比较大时,会出现精度丢失的问题。
四、decimal类型
该decimal类型,与float类型基本一样,区别在于decimal能更精确控制浮点数,确保不会丢失。
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
float 和 decimal 总结
说明:float表示的精度大约是7位。
decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略,
默认是10。
建议:如果希望小数的精度高,推荐使用decimal。
五、char类型(固定长度)
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
比如:name char(2),表示放的最大长度的字符串是2;
注意:在MySQL中,一个汉字表示一个字符!
六、varchar类型(可变长度)
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
在修改varchar的最大类型的长度时,发现最大字符长度是 21845,
这个是字符的长度,由于采用utf8编码,一个字符3个字节。
21845*3 = 65535
总结
但是,当我修改到21845时,同样不可以。
原因是:varchar(6),表示的是字符的使用上限是6,而不是一次固定分配6个字符大小的空间。
当只使用1个字符的空间时,varchar实际上只会分配一个字符大小的空间。所以,就需要有1~3个字节位,来记录所使用的空间有多少。
而char类型不同,char类型是直接一次给指定的空间,不管用没用完,都给那么多。
说明:
- 关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:
- varchar字节长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532。
- 当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844[因为utf中,一个字符占用3个字节],如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节)。
char和varchar比较
七、日期和时间类型
常用的日期有如下三个: date :日期 ‘yyyy-mm-dd’ ,占用三字节 datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从 1000 到 9999 ,占用八字节
timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss ,格式和 datetime 完全一致,占用四字节
创建一个表,如下:
create table if not exists t7(
-> d date,
-> dt datetime,
-> ts timestamp
-> );
首先插入一个数据:
时间戳timestamp就是当前的最新时间。
然后,修改d,如下:
发现时间戳ts改变了,变成了最新的时间。
时间戳(timestamp)存在的意义:
实际生活中的社交软件,视频下面会有评论,当一个人发表评论时,会被所有人看到,并且附带发表评论时的时间。
过了几个月,当这个人修改它发表过的评论时,时间会自动更新成当前时间!
这就能让所有人知道,该评论何时被评论的,何时被修改的。
datetime存在的意义:
入职的时间,固定在那里,或者办理身份证的时间,固定在那个时间,什么日期,几时几分几秒,一般不会自动更新。
date存在的意义:
比如记录一个重要的人的生日,比如你自己的生日。
八、enum和set类型
enum
enum类型:枚举
在插入时,可以直接插入枚举类型定义的常量,也可以直接插入枚举常量的下标。(这里的下标从1开始)
比如:创建一个表如下:
create table if not exists t8(
-> name varchar(30),
-> gender enum(‘男’,‘女’),
-> hobby set(‘代码’,‘羽毛球’,‘乒乓球’,‘足球’,‘游泳’)
-> );
可以这样插入:
- insert into t8 values(‘张飞’,‘男’,‘代码’);
还可以这样插入:
- insert into t8 values(‘孙权’,1,‘代码’);
结果如下:1就代表枚举常量中的下标,在此1表示男,2表示女。
set
set的选择可以按照位图来。
以上面的表为例,
hobby set(‘代码’,‘羽毛球’,‘乒乓球’,‘足球’,‘游泳’)
一共有五个爱好,那么位图就有5个比特位,为1时表示选择该爱好。
所以可以这样插入数据:
- insert into t8 values(‘孙权’,1,31);
31的二进制就是:11111,就会让上面set位图的5个比特位全部置1。
如果是这样插入:
insert into t8 values(‘孙权’,1,7);
7的二进制是:00111,代表将前3个比特位置1。
而前三位就是set的从左到右开始计算的。
所以爱好为:‘代码’,‘羽毛球’,‘乒乓球’。
总结
enum用数字来插入时,指代下标。
set用数字来插入时,指代位图,set的从左到右代表从小到大。
enum和set的类型查找
法1:
select * from votes where gender=1;
select * from votes where gender=‘男’;
上面两种写法等价。
根据特定的类型查找,比如按性别查找。
法2:
find_in_set 函数
select find_in_set(‘a’,‘a,b,c’);
- 1.find_in_set 函数是查找一个元素是否在集合里面。
- 2.判断一个元素是否在集合中,而不是判断是否严格相等。
所以,查找hobby是否有羽毛球时,是判断羽毛球是否在每一个用户中的。