上期我们在建表的时候用到了很多数据类型,下面就来详细讲解这些数据类型
目录
一、数据类型分类
二、对于一些数据类型的分析
2.1 数值类型
2.1.1 有符号和无符号类型
2.1.2 bit类型
2.1.3 浮点型
2.1.3.1 float
2.1.3.2 decimal
2.2 字符串类型
2.2.1 char
2.2.2 varchar
2.3 日期和时间类型
2.4 枚举和集合类型
2.4.1 enum类型
2.4.2 set类型
一、数据类型分类
我们先来概览一下MySQL下有哪些数据类型:
分类 | 数据类型 | 说明 |
---|---|---|
数值类型 | BIT (M) | 位类型。M指定位数,默认值1,范围1~64 |
TINYINT [UNSIGNED] | 带符号的范围-128~127,无符号范围0~255。默认有符号 | |
BOOL | 使用0和1表示真和假 | |
SMALLINT [UNSIGNED] | 带符号范围-2^15~2^15-1,无符号范围0~2^16-1 | |
INT [UNSIGNED] | 带符号范围-2^31~2^31-1.无符号范围0~2^32-1 | |
BIGINT[UNSIGNED] | 带符号范围-2^63~2^63-1,无符号范围0~2^64-1 | |
FLOAT[(M,D)] [UNSIGNED] | M指定数据总位数,D指定小数位数,占用4字节 | |
DOUBLE[(M,D)] [UNSIGNED] | 表示比float精度更大的小数,M指定数据总位数,D指定小数位数,占用空间8字节 | |
DECIMAL(M,D) [UNSIGNED] | 定点数M指定数据总位数,D表示小数点的位数 | |
字符串、文本类型 | CHAR(SIZE) | 固定长度字符串,最大255 |
VARCHAR (SIZE) | 可变长度字符串,最大长度65535 | |
BLOB | 二进制数据 | |
TEXT | 大文本,不支持全文索引,不支持默认值 | |
时间和日期类型 | DATE | 日期类型(yyyy-mm-dd) |
DATETIME | 日期类型(yyyy-mm-dd hh:mm: ss) | |
TIMESTAMP | 时间戳 | |
枚举和集合类型 | ENUM类型 | ENUM是一个字符串对象,其值来自表创建时在列规定中显示枚举的一列值 |
SET类型 | SET是一个字符串对象,可以有零或多个值,其值来自表创建时规定的允许的一列值。指定包括多个set成员的set列值时各成员之间用逗号间隔开。这样set成员值本身不能包含逗号。 |
接下来对一些常用类型进行讲解:
二、对于一些数据类型的分析
2.1 数值类型
2.1.1 有符号和无符号类型
在MySQL中,有的数值类型可以指定是有符号的和无符号的,默认是有符号的(这里拿TINYINT举例):
在上面我们创建了一个t1表,该表只有一个tinyint类型的属性列num,现在我们向这个表里面添加点数据:
我们可以看到可以向列中插入负数和正数,说明在没有UNSIGNED说明下该类型默认为有符号数
另外可以通过UNSIGNED来说明某个字段是无符号的:
向其插入数据:
不过要注意了,我们无法向其中插入超出该类型存储范围的数:
如果我们向mysql特定的类型中插入不合法的数据,MySQL一般都是直接拦截我们,不让我们做对应的操作!
所以在mysql中,数据类型本身也是一种约束,这样可以保证数据库中的数据是可预期,完整的。
2.1.2 bit类型
下面我们建一张存有bit类型的表t3:
现在我们向其中插入一些数据:
我们可以看到bit类型也是有限制的,因为我们创建的比特位只有一位,所以只能插入0和1两种数据
我们查看一下表中的数据看看:
奇怪,bit类型的数据怎么不打印出来呢?
这是因为bit类型的数据默认按ASCII编码的数据来打印,而0和1对应的格式是不显示的。
不过我们可以使用语句将其以十进制的格式打印出来
2.1.3 浮点型
2.1.3.1 float
我们可以定义float类型来表示小数:
float[(m, d)] [unsigned]
M指定数据总位数,d指定小数位数,占用空间4个字节
下面来分析一下float类型的使用:
我们现在向t4表中插入数据:
我们创建t4时float类型并没有使用unsigned说明,可以看到正负数都可以表示
现在我们继续向t4中插入数据:
我们可以看到上面三个数据不合法插入不了,这是因为我们在刚开始定义float时规定了其数据总位数为4个,其中小数位数占2个:当我们插入100.0这样类型的数据时整数位数为3个,但是不管我们100后面加的是几位小数,系统都会默认为两位,所以导致数据总位数为5位,超过了我们当初定义的范围。
那我们向该类型中插入小数位数超过两位数的数据呢?
这时系统可以让我们插入小数位数超过两位数的数据,不过显示出来还是两位小数的数据,并且会在原有数据的第二位小数位后面四舍五入!
如果按照超过规定小数位的数据后的数据进行四舍五入,那我们下面插入这样的数据试试看:
我们可以看到如果四舍五入过后的数据总位数没有超过规定位数是可以插入的,如果超过了就不合法了
在接下来,我们另创一个表,在该表内部设置一个float属性列,不过这个float类型我们并没有用来限定数据位数的类型:
我们向里面插入数据:
咦?这么大的数据也给插?我们来看看表中数据的情况:
这和原数据差别也太大了吧,所以我们可以看到原生的float虽然不会限制我们插入数据,但是数据位数过于多会造成精度的丢失!
2.1.3.2 decimal
decimal和float很像,但是有区别: float和decimal表示的精度不一样
我们现在来验证一下:
上面我们在一张表中创建了float(10,8)和decimal(10,8)两种类型的列f和d
现在我们存入相同的数据来看看:
我们看到float类型的数据最后一位与原数据不一样了
所以如果希望小数的精度高,推荐使用decimal类型。
2.2 字符串类型
2.2.1 char
char(L)
L是可以存储的长度,单位为字符,最大长度值可以为255
现在来实践一下:
插入数据:
我们可以看到当字符数超过2时就不让我们插入了,这个可以理解
下面我们用中文试试看:
居然也可以!我们知道在utf8编码下一个汉字占3个字节,两个汉字即6个字节
现在我们可以得出我们限定char类型的存储的长度时,真正是以字符为单位的,而不是字节。
2.2.2 varchar
varchar(L)
L表示字符长度
varchar类型存储容量最大为65535个字节,所以L最大值与编码格式有关
varchar类型最大虽然可以存储65535个字节,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532字节
当我们的表的编码是utf8时,varchar(L)的参数L最大值是65532/3=21844[因为utf中,一个字符占 用3个字节],如果编码是gbk,varchar(L)的参数L最大是65532/2=32766(因为gbk中,一个字符 占用2字节)
varchar类型的使用与char类型是一样的,那如何选择定长或变长字符串?
如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号
如果数据长度有变化,就使用变长(varchar), 比如:名字,地址。
定长的磁盘空间比较浪费,但是效率高。 变长的磁盘空间比较节省,但是效率低。
定长的意义是,直接开辟好对应的空间(类似于C语言中char类型数组)
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少(类似于C++中的容器string)
2.3 日期和时间类型
常用的日期主要有下面三个:
date :日期 'yyyy-mm-dd' ,占用三字节
datetime:时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp:时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节(timestamp数据类型的列不需要对其做修改)
话不多说,下面我们接着演示:
我们创建了t8这个含有date、datetime、timestamp三种数据类型的表,下面我们来插入数据:
可以看到,我们向表中插入数据时,timestamp类型的t3会自动记录当前的时间
那接下来我们对插入的数据做一些修改:
我们可以看到,当我们对数据做出修改时,该数据对应行中timesamp类型的数据会自动更新当前的时间!
2.4 枚举和集合类型
2.4.1 enum类型
enum('选项1','选项2','选项3'...)
enum类型可以提供若干个选项的值,插入数据时一个单元格中只能存储其中一个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,3,....最多65535 个;当我们添加枚举值时,也可以添加对应的数字编号。(这和C语言中的enum类型很像)
上面的说明过于生涩,我们下面用实例帮助理解:
现在我们向表中插入数据:
我们可以看到向表中插入数据时,不仅仅可以用enum里定义的字符串,还可以使用字符串对应的数字下标。在本表中enum类型中的'男'、'女'从左到右分别对应1、2这两个下标。
现在我们再来插入一些其他数据看行不行:
答案是不行的,我们在向enum类型中插入数据时只能插入其中存有的数据,使用下标时只有有效的下标才能生效。像这里的enum类型只有'男'、'女'分别对应1、2这两个下标,所以除了1/2其他的下标都是不合法的。
2.4.2 set类型
set('选项1','选项2','选项3'...)
set类型可以提供若干个选项的值,插入数据时一个单元格中可以存储其中任意多个值;而且出于效率考虑,这些值实际存储的是二进制数字,因为这些选项的每个选项值依次对应如下二进制数字:1(1),10(2),100(4),1000(8),10000(16),100000(32),.... 最多64个。
下面举例进行详解:
我们下面进行一些数据的插入:
我们可以看到set类型的列,一个单元格可以插入多个选项中的数据
下面我们试试看set类型是否可以像enum类型那样使用下标进行数据的插入:
咦?1和2是按照数据的下标进行插入的,怎么3就不是了呢?
这是因为enum类型插入数据的数字不是选项的下标,我们要把数字转化为二进制来看:
在该enum类型中一共有四个选项,分别对应着一位二进制数:
这时我们将数字3转换位4位的二进制数:0011
其中0代表没有该数位对应选项的数据,1代表有该数位对应选项的数据
这样子3表示的二进制数表示在1和2数位有对应选项的数据,而3和4数位没有对应选项的数据
即有set类型中选项1和选项2的数据,没有选项3和选项4的数据:
所以就造成了最后一个赵六的hobby列有篮球和滑雪两个数据
以此类推,下面插入4这个数字对应的二进制为0100:
所以我们可以看到最后一行的hobby列的数据只有一个高尔夫。
如果我们要想将选项全部选上呢?那对应的二进制数为1111,转换为十进制就是15:
不过下面有一种特殊情况:
当我们输入数字0时,即表示什么选项都没有,这时会插入一个空串作为数据。
在最后提一下set类型的查找往往要用到MySQL的内置函数find_in_set() ,该函数我们在后期会详细讲解。
本期博客到这里就结束了,我们下期不见不散~
更多MySQL技能请看:http://t.csdn.cn/W9dQl
博主努力更新中~