MySQL——3、数据类型
数据类型
- 1、数据类型分类
- 2、数值类型
- 2.1、tinyint类型
- 2.2、bit类型
- 2.3、小数类型
- 2.3.1、float
- 2.3.2、decimal
- 3、字符串类型
- 3.1、char
- 3.2、varchar
- 3.3、char和varchar比较
- 3.4、日期和时间类型
- 3.5、enum和set
1、数据类型分类
2、数值类型
2.1、tinyint类型
首先创建t1表,只有列属性num,类型为tinyint类型:
创建成功后我们可以通过以下三种方式查看表信息:
1、查看当前数据库存在哪些表:show tables;
2、查看表结构:desc t1;
3、查看创建表的信息:show create table t1 \G
接着我们向该表插入一些值:
由于tinyint的取值范围为-128~127,所以上面插入都是成功的。
下面试试插入范围之外的值:
在创建表的时候,指明tinyint类型,后面还可以跟上unsigned表示无符号类型。下面我们创建表t2,只有一个num列的无符号tinyint类型:
接着我们试着插入一些数据:
此时无符号的unsigned tinyint类型取值范围是0~255,我们插入范围内的值是可以插入成功的,当我们插入范围之外的值,MySQL会直接拦截我们。至于其他的类型,如small int、medium int、int、bigint可自行测试。
在C/C++中,我们赋值一个大整数给char类型的数据,一般情况下不会报错,会自动发生截断。而在MySQL中,如果我们向MySQL特定的类型插入不合法的数据,MySQL一般都是直接拦截我们,不让我们做对应的操作!反过来,如果我们已经有数据被成功插入到MySQL中了,那么插入的数据一定是合法的。
所以MySQL中,数据类型本身也是一种约束。——倒逼程序员,让程序员尽可能进行正确的插入。约束约束的是使用者。如果你不是一个很好的使用者,MySQL也能保证插入数据的合法性。
通过这种方式,就可以保证数据库中的数据是可预期的,完整的。
2.2、bit类型
使用样例:
表t3中的online用来表示用户是否在线,由于只有一个比特位,所以只能表示0/1,其中0表示不在线,1表示在线。我们插入数据,发现只能online这一列的时候,只能插入0/1,超出的数值是无法插入的。
另外我们查看一下插入的数据:
我们发现online这一列默认显示的是十六进制数,如果我们要转换成十六进制可以这样:
下面我们修改online这一列的属性,插入一些更大的数值看看:
另外,bit类型的位数是1~64,如果超出64位创建表的时候就会失败,如果不写位数默认就是1位。如下图:
2.3、小数类型
2.3.1、float
使用样例:
salary的取值范围在-99.99~99.99,所以其他数值是无法插入的。
插入的数据如果有多个小数,会进行四舍五入。当时需要注意四舍五入后也需要在取值范围内,假设插入数据为99.995,四舍五入后就是100.00,这样也是无法插入的。
下面我们再看看使用无符号float类型的样例:
float这里无符号类型很简单粗暴,直接将负数部分砍掉。
下面修改salary属性,改为默认的float类型,然后插入数据:
我们不指定位数和精度,默认也是只保留两位小数的,但是我们可以看到插入数据的时候,连整数精度都会丢失。
2.3.2、decimal
首先来对比float和decimal的精度:
我们发现float是有精度丢失的,而decimal精度更高
3、字符串类型
3.1、char
使用样例:
如图,大于两个字符就无法插入了。接着我们再验证一下汉字:
对于中文汉字也是如此。这里字符串char类型是以字符为单位的,不管是数字、字母、汉字,一个都算一个字符。另外,utf8mb3编码中,一个中文汉字一般是占3个字节,两个字符中文汉字那就是6个字节,而在gbk编码中,一个中文汉字则占2字节。
3.2、varchar
使用样例:
由于我们设定的长度为6,所以超过6个字符就无法插入了。另外,我们注意到上面最大长度为65535个字节,那么在utf8mb3编码下,我们需要让65535/3=21845个字符。
实际上,varchar还需要1~3个字节来记录数据的长度,假设长度拉满,那么实际上存储的字节数就是65532。如果是在utf8mb3中,就需要/3。如果是在gbk中,就需要/2。
在上图中,我们修改了字符长度为21845,由于还需要保存数据长度,所以肯定不行。但是为什么修改长度为21844也不行呢?这是因为MySQL中一行最大长度为65535个字节,我们前面还有一个int类型的数据,所以实际上最大也只能是21842个字符。
如果我们另外创建一个表,单独存放一个变长字符串,那么就可以达到21844个字符,这时候没有其他属性影响,那么该属性可以独占一行最大长度65535个字节。
3.3、char和varchar比较
3.4、日期和时间类型
使用样例:
timestamp在MySQL比较老的版本中,当我们进行插入或者修改的时候是会自动进行更新的。但是这里我使用的MySQL8.0,所以不会自动更新了,需要我们再创建表的时候设置,如下:
MySQL较新的版本需要我们手动显示定义。现在当我们插入一行或者修改属性的时候,第三个字段timestamp就会自动更新:
timestamp可以应用在用户发表评论的时候,当用户发表了,插入评论信息到数据库中,自动设置时间戳。当用户修改评论的时候,对应数据库的时间戳也会自动修改。datetime就是用来存储固定的时间的。
3.5、enum和set
使用样例:
gender性别不能插入除男和女以外的值,当然也可以采用常量的下标1/2,从下标1开始,下标也不能超出范围。
插入集合的时候,也是不能出现除集合意外的值。可以插入多个选项,中间用逗号分隔开。
另外,我们发现enum和set默认是可以为空的,所以在插入表t13的时候,我们可以只插入username,剩下的gender和hobby默认为空。
接着我们给hobby插入了一个0和一个1,我们发现插入0的这一行hobby为空。这就需要对比NULL和’'了,NULL表示为空,而这里则表示空串。空串和NULL是不一样的。插入1则表示的是代码。
下面我们插入2,那么对应的应该就是羽毛球了:
那如果我插入3呢?是乒乓球吗?
并不是,这里是代码和羽毛球。因为代码是用第一个比特位来表示的,羽毛球是用第二个比特位来表示的。插入3,3的二进制表示为11,所以插入了代码和羽毛球。所以乒乓球应该是第三个比特位来表示的,如果我们想单独插入一个乒乓球用数字的方式,那么就应该插入4。
hobby总共有五个选项,每个选项对应第一个比特位到第五个比特位,如果我想插入所有的选项呢?那就是2^5-1=31。下面我们插入31看看:
enum和set的查询:
enum查询我们可以使用枚举常量,也可以使用下标来查询。
我们在查询set的时候,这里的查询条件是严格匹配的,显示的是只有爱好为羽毛球/代码+羽毛球的人员信息。但是我们还期望的是筛选出爱好包含羽毛球的所有人员信息,就需要使用find_in_set函数。
那如果我们要找爱好中包含羽毛球和代码的呢?我们上面测试在abc中查找ab返回是0。
实际上我们where子句可以跟and,把多种结果级联起来。关于where子句我们后面会做介绍。