MySQL数据库精研之旅第三期:数据类型背后的秘密

发布于:2025-03-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

专栏:MySQL数据库成长记

个人主页:手握风云

目录

一、常用数据类型分类

二、数据值类型

2.1. 类型列表

2.2. 数据类型取值范围

三、字符串类型

3.1. 类型列表

3.2. 关于排序

3.3. CHAR与VARVHAR的选择

四、日期类型

4.1. 类型列表

4.2. 其他


一、常用数据类型分类

        我们知道,库是管理数据的最大集合,库里面有很多的数据表,表是由数据行构成的。在面向对象软件开发的过程中,通常会先进行需求分析从而得到类和属性。我们先来看下面的一段Java代码:

class Student{
    public int age;
    public boolean geder;
    public String name;

    public Student(int age, boolean geder, String name) {
        this.age = age;
        this.geder = geder;
        this.name = name;
    }
}

public class Solution {
    public static void main(String[] args) {
        Student stu1 = new Student(19,true,"张三");
        Student stu2 = new Student(20,false,"李四");
    }
}

        类是⾯向对象中的概 念,对应到数据库中的概念就是实体,类中的属性对应实体中的属性。实体通常以表的形式存在,每个实体对应⼀张表,表中的每条数据行就是实体的⼀个实例。

        如果要定义实体的属性,就要为属性命名并指定合适的数据类型。与其他编程语⾔类似,SQL中规定了⽤于描述属性的数据类型。常用的数据类型有以下几类:

  • 数据值类型
  • 字符串类型
  • 二进制类型
  • 日期类型

        数据值类型、字符串类型、日期类型我们在Java中经常用到,而二进制类型对应到Java中的byte数组,以二进制的形式存储并往后排。

二、数据值类型

2.1. 类型列表

类型 大小 说明
BIT[(M)] 默认bit 位值类型。M表⽰每个值的位数,取值范围为 1 ~ 64 。如果省略M,则默认为1。
TINYINT 1byte 取值范围 -2^7 ~ 2^7-1 ,无符号取值范围 2^8-1
BOOL 1byte TINYINT(1)的同义词。值为零被认为是假,⾮零值被认为是true
SMALLINT[(M)] 2byte 取值范围 -2^15 ~ 2^15-1 ,⽆符号取值范围 2^16-1
MEDIUMINT[(M)] 3byte 取值范围 -2^23 ~ 2^23-1 ,⽆符号取值范围 2^24-1
INT[(M)] 4byte 取值范围 -2^31 ~ 2^31-1 ,⽆符号取值范围 2^32-1
INTEGER[(M)] 4byte INT[(M)]的同义词
BIGINT[(M)] 8byte 取值范围 -2^63 ~ 2^63-1 ,⽆符号取值范围 2^64-1
FLOAT 4byte 单精度浮点型,M是总位数,D是⼩数点后⾯的位数,⼤约可以精确到⼩数点后7 位
DOUBLE 8byte 双精度浮点型,M是总位数,D是⼩数点后⾯的位数,⼤约可以精确到⼩数点后 15位。
DECIMAL[(M,D)] 动态 不存在精度损失,M是总位数,D是小数点后的位数。DECIMAL的最⼤位数(M)为 65,最大小数位数(D)为30。

        由于FLOAT和DOUBLE的精度问题,一般在系统开发时不使用这两种数据类型。关于DECIMAL是如何实现精度不受损失的,其实是对一个大数每9位进行拆分,每一份用int来储存,int最大可以储存21亿的数字,再用诺干个int进行表示,而剩余的小数部分则用最小的数据类型来存储。而在真实的开发过程中,尤其像银行和金融这种涉及到大量金额的公司,既使用DECIMAL进行表示表示,但比较麻烦也可以使用int进行存储记录。

2.2. 数据类型取值范围

类型 大小 有符号最小值 有符号最大值 无符号最小值 无符号最大值
TINYINT 1byte -128 127 0 255
SMALLINT 2byte -32768 32767 0 65536
MEDIUMINT 3byte -8388608 8388607 0 16777215
INT 4byte -2147483648 214783647 0 4294967295
BIGINT 8byte -2^63 2^63-1 0 2^64-1

三、字符串类型

3.1. 类型列表

类型 说明
CHAR[(M)] 固定⻓度字符串, M 表示长度,以字符为单位,取值范围 0 ~ 255 , M 省略则长度为1
VARCHAR(M) 可变⻓度字符串, M 表示字符最大长度,范围0 ~ 65535 ,有效字符个数取 决于实际字符数和使⽤的字符集
TINYTEXT 小文本类型,最大长度为 255 (2^8 - 1)个字符,有效字符个数取决于使用的字符集
TEXT[(M)] 文本类型,最大长度为 65535 (2^16 - 1)个字符,有效字符个数取决于使用的字符集
MEDIUMTEXT 中文本类型,最大长度为 16,777,215 (2^24 - 1)个字符,有效字符个数取决于使用的字符集
LONGTEXT 大文本类型,最大长度为 4,294,967,295 即 4GB (2^32 - 1)个字符,有效字符个数取决于使用的字符集
BINARY[(M)] 固定长度⼆进制字节,与CHAR类似,但存储的是⼆进制字节而不是字符串。 M 表示长度,以字节为单位,取值范围 0 ~ 255 ,M省略则长度为1
VARBINARY[(M)] 可变长度⼆进制字节,与VARCHAR类似,但存储的是⼆进制字节而不是字符串。 M 表示长度,以字节为单位
TINYBLOB[(M)] 小⼆进制字节类型,最大长度为 255 (2^8 - 1)个字节
BLOB[(M)] ⼆进制字节类型,最大长度为 65535 (2^16 - 1)个字节
MEDIUMBLOB 中⼆进制字节类型,最大长度为 16,777,215 (2^24 - 1)个字节
LONGBLOB 大⼆进制字节类型,最大长度为 4GB (2^8 - 1)个字节
ENUM('value1','value2',…) 枚举;从值列表 'value1','value2' 或 ''(空字符串) 和 NULL 中选⼀个值;最多可以有 65,535 个不同的元素
SET('value1','value2',…) 集合;从值列表 'value1','value2' 中选零个或多个值;最多64个元素

        CHAR的固定长度,比如指定10个字符,却只是用3个字符,长度依然是10个;VARCHAR的取值范围决定了能存储字符的最大个数65535/4=16383(当使用utf8mb4字符集时)。对于文本类型和二进制类型,我们用记事本的形式打开一个Excel文档,会发现里面都是我们看不懂的一堆乱码,这就是二进制类型。由于太浪费空间,现在MySQL已经不存这些二进制类型的数据了,有更好的方式去保存。

3.2. 关于排序

  • 字符串类型的列以字符为单位,并且可以单独指定字符集和排序规则,比如字符集是 utf8mb4 ,排序规则是 utf8_0900_ai_ci
  • ⼆进制的列以字节为单位,可以指定_bin结尾的排序规则,比如排序规则是 utf8mb4_bin ,这 时以比较和排序基于数字字符代码值

3.3. CHAR与VARVHAR的选择

  • 如果数据确定长度都⼀样,就使用定长CHAR类型,比如身份证,学号,邮编等。比较浪费磁盘空间,但是效率⾼。
  • 如果数据长度有变化,就使⽤变长VARCHAR,比如:名字,地址,但要规划好长度,保证最长的字符串能存的进去。比较节省磁盘空间,但是效率低。

四、日期类型

4.1. 类型列表

类型 大小 说明 0值
TIMESTAMP[(fsp)] 4byte
  • 时间戳类型
  • ⽀持范围 1970-01-01 00:00:01.000000 ~ 20388-01-19 03:14:07.499999
0000-00- 00 00:00:00
DATETIME[(fsp)] 8byte
  • 日期类型和时间类型的结合
  • 支持范围 1000-01-01 00:00:00.000000 ~ 9999-12-31 23:59:59.499999
  • 显示格式为 YYYY-MM-DD hh:mm:ss[.fraction]
0000-00-00 00:00:00
DATE 3byte
  • 日期类型
  • 支持范围 1000-01-01 ~ 9999-12-31
  • 显示格式为 YYYY-MM-DD
0000-00-00
TIME[(fsp)] 3byte
  • 时间类型
  • ⽀持范围 -838:59:59.000000 ~ 838:59:59.000000
  • 显示格式为 hh:mm:ss[.fraction]
00:00:00
TEAR[(4)] 1byte
  • 4位格式的年份
  • 支持范围 1901 ~ 2155
  • 显示格式为 YYYY
0

        TIMESTAMP类型的日期如果超出范围就会溢出,返回到1970-01-01 00:00:01.000000,一般我们也不要用;最常用的就是DATETIME、DATE、TIME这三种类型;fsp为可选设置,⽤来指定⼩数秒精度,范围从0到6,值为0表示没有小数部分,如果省略,默认精度为0。

4.2. 其他

  • CURRENT_DATE 和 CURRENT_DATE() 是 CURDATE() 的同义词用于获取当前日期
  • CURRENT_TIME 和 CURRENT_TIME([fsp]) 是 CURTIME() 的同义词用于获取当前时间
  • CURRENT_TIMESTAMP 和 CURRENT_TIMESTAMP([fsp]) 是 NOW() 的同义词用于获取当前日期和时间
mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2025-03-25 10:52:32 |
+---------------------+
1 row in set (0.00 sec)

mysql> select curdate();
+------------+
| curdate()  |
+------------+
| 2025-03-25 |
+------------+
1 row in set (0.00 sec)

mysql> select current_time();
+----------------+
| current_time() |
+----------------+
| 10:53:59       |
+----------------+
1 row in set (0.00 sec)