目录
介绍
- mysql中,可以在表中定义不同的列字段,用于表示表的属性
- 每个列都有一个数据类型,它决定了该列可以存储的数据种类和在数据库中的存储方式
约束
- 每个类型都有自己的范围
mysql规定插入数据时不能超范围 -- 这属于一种约束
mysql约束了程序员的不合规行为,那么,数据库中存放的数据就都是合法的
整数类型
![](https://i-blog.csdnimg.cn/blog_migrate/10195984f75658b15b9ce4caedfb5656.png)
示例
有符号整数
我们这里用tinyint作为示例,有符号tinyiint的范围是-127~128
括号的意义
注意,这里类型后面的括号里是4,这是什么意思呢?
- 实际上表示的是它的显示宽度
- 因为它的最大值和最小值都是3位数,并且有可能为负数,所以宽度是1(负号)+3(三位数)=4
插入超范围数据
可以看到,127和-128都成功插入,但128和-129都有警告
但可以成功插入,并且插入后的值是范围临界值:
无符号整数
括号
注意新创建的属性列num_u,它的长度是3,因为无符号类型不会是负数,所以长度比有符号的-1
插入超范围数据
无符号tinyint的范围是0~255
所以,当我们插入256时会出现警告,但仍可以插入,且插入数值为范围边界值:
设置严格模式
引入
上面两种类型超出范围后,都是使用范围边界值继续进行插入(也就是将插入的数值截断了)
但如果我们不想这样,而是让他直接报错呢?
解决
- 在当前mysql中直接设置 SET sql_mode='STRICT_TRANS_TABLES'; (重新登录后失效)
- 可以修改my.cnf配置文件,添加 sql_mode=STRICT_ALL_TABLES
- (但不知道为什么,我修改了好多好多次配置文件,试了好几种格式,都没生效,查的方法写的格式各不相同,尊嘟很崩溃,但是set的方式确实可行(赞),大不了以后如果需要操作数据,记得加设置也行(瘫倒))
示例
当我们设置好严格模式后,插入超范围数据,就会直接报错且不进行插入操作:
可以用select查看此时的sql_mode设置
不同范围的用途
设定多种不同范围的类型,是为了减少资源浪费
- 假设某个变量不会超过1bit,但你为他申请了8bit,那么每有一个数据就会浪费7bit,数据量越大,资源浪费越多
- 不同范围的int同理,如果这个变量最大值不会超过100,就没有必要为他提供更大的空间,tinyint足以
布尔类型(bool)
本质
- 从图中可以看到,虽然我们设置了bool类型,但在查看属性的时候,显示的却是tinyint(1)
- 所以,其本质就是tinyint,只不过长度是1(所以,虽然他可以插入0和1以外的一位数字,但我们一般不这么使用)
位类型
bit(n)
n的含义
- n代表有n位bit
- n的范围 : 1~64
- 如果不输入n,则默认为1
- 该属性列插入的数值不能超过n位bit可以表示大小的范围(也就是2^n-1)
示例
我们设置了2位bit大小的address,所以它表示的范围为0~3
所以插入4时会报错:
无法回显
ASCII码形式
select查看时,不能回显,因为它以ASCII码的形式显示
- 我们可以先试着插入97(我们都知道它代表的是字母a):
- 查询ASCII码表后,我们会发现,先前插入的是0,1,3,这三个数字代表的ascii码都不是可以回显的字符
- 从32开始,才是可以看到的
- 比如我们插入32,会看到,他比插入无法回显的字符多了一个格,那个格就是空格字符
解决方法
hex(属性列)
返回二进制数据的十六进制表示
bin(属性列)
将二进制数值转换为二进制字符串
conv(属性列,原进制,转换后的进制)
指定进制转换
浮点数类型
float(m,d) (unsigned)
m的含义
表示显示长度(是整个数字的长度)
- eg:25.1的显示长度为3
d的含义
表示小数位数
- eg:25.1的小数长度为1
下面使用(4,2)作为例子:
小数部分
超出d
遵循四舍五入(在边界值内)
不足d
会用0填充
整数部分
不可以超出m-d
- 四舍五入导致整数部分超过(m-d)也不行:
有无符号
默认下
默认情况下是有符号的
- 所以,上面的(4,2)可以表示的范围就是 -99.99 ~ 99.99:
无符号时
只允许插入0和正数
- eg:float(4,2) -- 0 ~ 99.99
double(m,d) (unsigned)
用法和float一样
和float的区别
实际上,区别只在于占据的空间不同
- float占用4字节
- double占用8字节(可以表示更大的精度)
精度损失
引入
我们新创建两个使用默认范围的float和double类型的属性:
使用默认范围时: 整数和小数均有精度损失
因为float和double类型存储时,都需要转为二进制(也就是标准格式)
示例
当我们插入整数和小数部分均很大的数字时
- 会发现float只有整数部分,double的存储情况良好
当插入只有小数部分大的数据:
- 整数部分均正确,但float仅存了3位小数,double存放良好
小数部分更大时:
- 会发现double的最后一位小数存储错误
原因
以上就是float和double存在精度损失的示例
究其根本,是因为这两种类型都是以IEEE标准格式存放的:
- 需要进行十进制->二进制的转换,但是小数部分的转换是每次*2取整,不是每个数字的转换都会刚刚好,所以必然会存在精度损失
decimal(m,d) (unsigned)
优势 -- 没有精度损失
它的用法和前两种类型是相同的,但是,他有一个独特的优势 -- 没有精度损失
- 为相同范围的float和decimal插入同样的数据
- 一旦数字长度较长,float因为一些原因,会产生精度损失,导致数据数值变化(double也同理)
- 而decimal并不会
示例
创建相同范围的float和decimal属性列:
插入相同的数据,会发现float类型的后两位小数不正确,而decimal类型的数据完全相同:
字符串类型
char(L)
L的含义
L为该字符串的最大字符数
最大为255
字符的含义
- 之前认识的字符 -- 一个字节
- mysql中的字符 -- 一个符号(无论是字母/数字/中文字符,都属于一个字符),所以,一个字符的大小被设置为3个字节(为了可以容纳最大的字符)
示例
插入数值:
插入字母和中文:
超出范围
如果不是严格模式:
它会自动截断,插入内容的长度为L
严格模式下:
定长字符串
无论你使用了多少空间,都会直接开辟3*L个字节的空间,来完整容纳L个字符
varchar(L)
用法和char类似,唯一不同的就是verchar是变长字符串
变长字符串
- 也就是说,你插入了几个字符,就开辟几个字符的空间
- 其最大空间为65535个字节(具体对应的符号数,取决于此时的编码格式,编码格式决定了一个字符=多少个字节)
- 为了知道此时的字符数,需要1-3个字节来存放字符数,所以有效字节数为65532
- (1-3个字节的范围,是按照数据量的大小,来确定实际用几个字节来存储的)
示例
当我们的表的编码是 utf8 时, varchar(n) 的参数 n 最大值是65532/3=21844(因为 utf 中,一个字符占用3 个字节) 如果编码是 gbk , varchar(n) 的参数 n 最大是 65532/2=32766 (因为 gbk 中,一个字符占用2 字节)
两者关联
char和varchar类似于char数组和string的关系
那么定长和变长也就不难理解了
最大存放空间
除了由自身决定(char和varchar表示的范围不同),也由其他属性列的大小决定
示例
当我们已经存在其他属性列时,再使用varchar类型,就不能开辟其理论上的最大值了:
因为mysql是按照行存储的
日期和时间类型
date
可以存储日期
数据格式为'yyyy-mm-dd' ,占用3字节
示例
插入数据时,如果不足指定位数,由0填充:
datetime
可以存储日期和时间
格式为 'yyyy-mm-dd HH:ii:ss' ,占用八字节
timestamp
时间戳,格式和 datetime 一致,占用四字节
它会自动更新(在插入数据/更新其他数据时,自动更新),不需要自行插入
可以记录该行数据上次添加/修改的时间
示例 -- 修改设置
如果没有自动更新的话,需要修改一下timestamp类型的设置:
alter table t_test modify ts timestamp default current_timestamp on update current_timestamp;
修改完后,插入某个数据,时间戳会自动更新其数据:
枚举和集合类型
enum('xx'...)
介绍
它允许你在列中定义一个有限的可能值集合,列中的值必须是预定义的枚举值之一
- 需要在创建该列时,就给出包含的选项 格式('xx','xx' ...)
- 虽然提供了若干个选项,但最终在一个单元格中只存储其中一个值(也就是说,只能单选)
插入
可以直接插入之前提供的选项:
也可以插入限定的常量/常量代表的下标(从1开始):
查找
如果我们想要查找所有选择了某个选项的数据:
select * form 表名 + where 列名='xx' / 下标
set('xx'...)
和enum基本一样,唯一区别就是,set可以允许一个实体具有多个属性(也就是可以多选)
插入
我们这里设置了三个选项:
插入数据时,将多个数据以,分隔 -- 'xx,yy,zz':
也可以插入数字,但这里数字表示的含义和enum中的并不相同
数字的含义
如果有3个常量,就对应3个bit位
eg:
插入0:000 (插入的是空串):
空串和null的区别
- 注意,空串和null本质上是不一样的,mysql看见两者的也是不一样的
- 空串是有内容,但内容为空
- null是内容不存在
插入3(011):
插入4(100):
插入7(111):
- 这样就是将选项全部插入了
查找 -- 模糊查找
可以采用enum中的形式,但那样是精准查询:
如果我们想要模糊查询呢?
find_in_set(元素,集合)
- 这个函数可以查询某一个元素是否在集合中
- 只要存在,就返回真
- 所以我们需要模糊查询表中元素的时候:
select * form 表名 + where find_in_set(值,列名)
- where类似于条件判断if
示例 -- 单个
可以看到,这样查询出来的结果,就是找到所有包含'看漫画'的数据:
如果想要查找同时包含多个值呢?
select * form 表名 + where find_in_set(值1,列名) and find_in_set(值2,列名)
and类似于c语法中的&&
示例 -- 多个