文章目录
- 前言
- 一、数据类型
- 数据类型分类
- 数值类型
- bit类型
- 小数类型
- float
- decimal
- 字符串类型
- char
- varchar
- char和varchar比较
- 日期和时间类型
- enum和set
前言
一、数据类型
数据类型分类
数值类型
下面我们来创建一个表,表中创建一个tinyint类型的数据。当我们不指定tinyint为无符号类型时,tinyint默认为有符号类型整数。在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。可以通过UNSIGNED来说明某个字段是无符号的
下面我们向表中插入数据。我们看到当向表中插入tinyint范围内的数据时,可以成功插入。当插入的数据不在tinyint时,会直接插入失败。
下面我们创建一个表t2,该表中的tinyint类型为无符号整型。
下面我们向表中插入数据,我们看到当插入的数据超过tinyint的范围时,数据库是不允许插入数据的。
通过上面的例子,我们知道了当向数据库中插入不合法的数据时,MySQL会直接插入数据失败,通过这样对数据的约束,MySQL就保证了表中的数据都是合法的。上面我们只测试了tinyint类型,但是在MySQL中其它的数值类型,例如int,bigint等的特性和tinyint一致。
bit类型
bit类型为位类型。基本语法如下:
bit(M) //M表示每个值的位数,范围为1-64,如果M忽略,那么默认为1。
下面我们创建一个表t3,并且让online设为bit(1)类型,那么这个online就只能存储1或0了。
我们看到如果插入的数据超过bit(1)类型的范围,那么就会插入数据失败。
我们看到显示数据时,online的数据并没有显示,这是因为bit字段在显示时,是按照ASCII码对应的值显示。
,而因为ASCII为1和0的这个字符不能显示,所以什么都看不到。
下面我们将online的数据为十进制显示,我们可以看到了。
下面我们验证bit类型存储的是字符的ASCII码值。我们先修改online的类型为bit(10),然后我们插入字符’a’和97,显示数据时都显示了字符’a’。因为字符’a’的ASCII码值为97。
小数类型
float
语法:
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节。
例如:小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。
下面我们创建一个选项salary为float(4,2)类型的数据,表示该浮点类型的显示长度为4,小数位数为2。如果不显示定义unsigned,那么默认为有符号类型。
create table t1(id int, salary float(4,2));
然后我们向表中插入数据。可以看到当插入数据的精度不够两位时会自动补为两位。如果要求精度为两位,但是插入的数据精度为三位,那么会进行四舍五入。
下面我们创建一个新表,并且定义一个类型为unsigned的float(4,2)的浮点数。然后向表里面插入数据,我们看到只能插入0~99.99范围内的合法数据。
decimal
语法:
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数.
例如:decimal(5,2) 表示的范围是 -999.99 ~ 999.99。decimal(5,2) unsigned 表示的范围 0 ~ 999.99。
decimal和float很像,但是有区别:float和decimal表示的精度不一样。
下面我们创建一个表来进行标记decimal和float的区别。我们看到float存储小数位比较多时,当第7位就会出现精度丢失,而且当我们规定float存储小数点后8位时,而输入的数据不到8位时,float存储的数据只有前面的是准确的。而decimal类型存储的数据一直都是准确的。所以当我们想要存储的小数精度更准确时,可以选择使用decimal类型存储。并且float表示的精度大约是7位。而decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0。如果m被省略,默认是10。
字符串类型
char
语法:
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255。
下面我们创建一个表,其中name选项为char(2)类型。我们看到当插入的字符串长度超过定义的长度时,会插入数据失败。并且我们看到当插入两个汉字时会插入成功,而出现三个汉字时会插入失败。我们知道一个字符为1个字节,一个汉字在utf_8中为3个字节,那么两个汉字就为6字节了,为什么还能插入成功呢?这是因为MySQL中的char的单位为字符,而不是字节。如果这个表采用utf_8字符集的话,那么每个字符的大小就为3个字节,当定义char(2)时,就会直接开辟6字节的空间。
char字符串可以存储的最大长度为255。当我们有超过255的字符串时,就需要使用变长字符串varchar来存储了。
varchar
语法:
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节(注意单位为字节)。
下面我们创建一个新表,然后设置name选项为varchar(6)类型,则表示name选项只能存储6个字符。
下面我们来改变name选项的类型为varchar(65535)。我们发现提示说varchar的最大长度为21845。然后我们将varchar长度修改为21845后,还是更改失败。这就和varchar的len有关了。
关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:
varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532。
当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844[因为utf8中,一个字符占用3个字节],而上面我们的测试中varchar为21844也出错了,这是因为MySQL中允许一行数据最大为65535字节,而我们的int占4个字节,所以需要再减去4字节。如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节)。
下面我们来验证utf8字符集下varchar最大长度为21844,gbk字符集下varchar最大长度为32767。
char和varchar比较
我们可以看到当使用定长char时,不管字符串的长度够不够规定的,MySQL都会开出长度 * 字符大小的空间。而varchar可以根据字符串的长度来开空间。可以看到varchar的总占用字节会多出来1-3个字节,当字符串长度较小时,1个字节就可以存长度。当字符串长度较大时需要3个字节存长度。
如何选择定长或变长字符串?
- 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
- 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
- 定长的磁盘空间比较浪费,但是效率高。
- 变长的磁盘空间比较节省,但是效率低。
- 定长的意义是,直接开辟好对应的空间
- 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
日期和时间类型
常用的日期有如下三个:
- date :日期 ‘yyyy-mm-dd’ ,占用三字节。
- datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从 1000 到 9999 ,占用八字节。
- timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节。
下面我们创建一个包含这三个日期类型的表。
我们看到当我们插入数据时,并没有给t3值,但是t3自动存储了当前时间。并且当我们更新表中的内容时,timestamp类型的t3会自动更新时间。
enum和set
语法:
-
enum:枚举,“单选”类型;
-
enum(‘选项1’,‘选项2’,‘选项3’,…);
该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,3,…最多65535个;当我们添加枚举值时,也可以添加对应的数字编号。 -
set:集合,“多选”类型;
-
set(‘选项值1’,‘选项值2’,‘选项值3’, …);
该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32,… 最多64个。
下面我们创建一个含义enum类型和set类型的表。
当我们向表中插入数据时,我们看到gender选项可以填我们的枚举值,也可以填1或2,但是除此之外的其它值都不可以填写。其实我们填入的1,2就是enum类型枚举的选项的下标。
下面我们看到当对hobby选项插入数据时,因为hobby为set类型,所以可以插入多个列举的内容,以逗号为分割。但是不能插入set没有列举的内容。
set类型插入也可以使用数字,但是set类型使用数字插入时,数字并不是列举的内容的下标。而是位图。即如果是1,1的二进制为00001。如果是2,2的二进制为00010。如果是3,3的二进制为00011。如果是4,4的二进制为00100。所以这就对应了。
enum的查找我们可以使用枚举的字符,也可以使用下标。
我们看到set的查找可以使用字符串,也可以使用位图。但是我们发现set的查找是严格匹配的,即当我们查’代码’时,只会把hobby为’代码’的显示出来。而当我们想要查看hobby中包含’代码’的数据时,该怎样查看呢?
此时我们可以使用集合查询函数,find_ in_ set函数。
find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0; str_list 用逗号分隔的字符串。
例如下面的一个find_in_set函数的案例。
下面我们就可以使用find_in_set函数来插入表votes中hobby包含羽毛球的人了。
当我们想要查看hobby同时包含羽毛球和代码的人时,可以使用and连接两个find_in_set函数的结果。