【MySQL】MySQL中的数据类型详解

发布于:2025-04-22 ⋅ 阅读:(98) ⋅ 点赞:(0)

目录

一、MySQL经典数据类型一览:

二、数值类型:

整形家族:

BIT:

三、小数类型:

float:

decimal:

四、字符串类型:

char:

varchar:

char和varchar区别:

五、时间日期类型:

六、enum与set类型:

enum:

set:

集合中的查询:


一、MySQL经典数据类型一览:

数值类型:

整数类型:

类型 存储空间 有符号范围 无符号范围 示例
TINYINT 1 字节 -128 ~ 127 0 ~ 255 年龄
SMALLINT 2 字节 -32768 ~ 32767 0 ~ 65535 小范围计数
MEDIUMINT 3 字节 -8388608 ~ 8388607 0 ~ 16777215 中等范围数值
INT 4 字节 -2³¹ ~ 2³¹-1 0 ~ 2³²-1 用户ID、订单号
BIGINT 8 字节 -2⁶³ ~ 2⁶³-1 0 ~ 2⁶⁴-1 大整数(如分布式ID)
  • 使用unsigned禁止负数,扩大正数范围
  • BOOL类型在MySQL中表现是tinyint的别名,存储0(假)或1(真)

小数类型

类型 存储空间 描述 示例
FLOAT 4 字节 单精度浮点数,近似值 科学计算数据
DOUBLE 8 字节 双精度浮点数,更高精度近似值 高精度测量值
DECIMAL(M,D) 变长(M+2字节) 精确小数,M=总位数,D=小数位 金额 DECIMAL(10,2)
  • decimal适合精确计算(如财务数据),避免浮点误差
  • float和double可能丢失精度,适合非精确计算

日期和时间类型

类型 存储空间 格式 范围 示例
DATE 3 字节 YYYY-MM-DD 1000-01-01 ~ 9999-12-31 生日、事件日期
TIME 3 字节 HH:MM:SS -838:59:59 ~ 838:59:59 持续时间
DATETIME 8 字节 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 订单创建时间
TIMESTAMP 4 字节 Unix时间戳 1970-01-01 00:00:01 UTC ~ 2038-01-19 UTC 最后登录时间(自动更新)
YEAR 1 字节 YYYY 1901 ~ 2155 年份

字符串类型

类型 最大长度 描述 示例
CHAR(n) 255 字符 定长字符串,适合短且固定长度 国家代码 CHAR(2)
VARCHAR(n) 65535 字节 变长字符串,适合长度变化数据 用户名、地址

特殊类型

类型 描述 示例
ENUM 枚举值(单选) 性别 ENUM('男','女')
SET 集合值(多选) 标签 SET('A','B','C')

二、数值类型:

整形家族:

数据类型 字节数 带符号最小值 带符号最大值 无符号最小值 无符号最大值
TINYINT 1 -128 127 0 255
SMALLINT 2 -32768 32767 0 65535
MEDIUMINT 3 -8388608 8388607 0 16777215
INT 4 -2147483648 2147483647 0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807 0 18446744073709551615

首先用SQL语句创建一个表,在其中测试smallint和tinyint unsigned

注意:SQL语句中创建无符号的类型是在类型后面加上unsigned

SQL语句:

create table if not exists student(
    id smallint,
    age tinyint unsigned
};

接着我们向表中插入在其范围中的语句,是能够插入的

那我们试试向表中插入不在其中范围的语句:

当向age插入负数的时候,是不可以的,因为其是无符号的,是非负的,会插入失败

也不能插入的数据不在它们表示的范围中,也会失败的

由此可见:

  • MySQL对数据的检测是严格的,会直接拦截非法的数据插入
  • 也就是说,只要是插入成功的数据,就一定是合法的

BIT:

基本语法:

bit[(m)]:这是位字段类型,m表示每个值的位数,范围是1~64,如果不写m,默认为1

create table t1( sex bit(1), a bit(2), aa bit(8) );

接着我们向其中插入些许数据:

可以看到这是以十六进制进行存储的

那么我们插入其他不成功的数据看看:

仔细观察,我们会发现其数据范围是按照位数来进行判断的:

  • bit(1)代表着只有1位 所以我们只能插入1或者0
  • bit(2)代表着有2位 也就是00 01 10 11代表着0,1,2,3
  • bit(8)代表着有8位 所以最大是1111 1111也就是1 0000 0000 - 1的结果 也就是255

如上以此类推

三、小数类型:

float:

基本语法:

float[(m,d)] [unsigned]:其中m表示总共显示的长度,表示小数点后面的位数,其占4字节

create table t2(
浮点数 float(6,3)
);

这样,其范围按照定义来说是-999.999~999.999,在该范围下的数据都能够成功插入

这里如果插入的时候后面比标准的小数点要少的话,会自动补齐0

这里如果插入的时候后面比标准的小数点要多的话,会四舍五入

浮点数如果是无符号的话,比如 float(6,3) unsigned 这样的话其范围是把负数那部分直接砍掉,就是0~999.999

float存在精度损失:

当对其进行插入操作后,然后在进行查看,发现其精度存在损失

double和float的使用基本是一样的,只是存储的范围大些,要想追求高精度,就需要使用类型decimal

decimal:

decimal使用方法大致和float基本差不多,在存储浮点数时,decimal能够更好地保证小数的精度

首先创建一个表,其类型为decimal

然后向表中插入和之前float丢失的精度的数据,然后进行查看

所以:

对精度的要求不是很高的,使用float或者double存储浮点数即可
对精度的要求很高的,使用decimal存储浮点数

四、字符串类型:

char:

char(L)是固定字符串,其中L是存储的长度,最大为255

首先创建一个表,里面有一个字段名称为name,类型为char(5)

所以,我们向表中插入字符串的长度不能超过5个,这个无论是汉字还是英文字母都是这样的

这里char不是按照字节来进行查看的,这里和C/C++是不一样的,这里是按照个数来看的,无论是英文字母还是汉字,都是满足其对应的个数即可

这样,用户在编码的时候就不必在意字节上的差异了

最后注意char类型最大长度为255

varchar:

char是固定字符串,在定义后是不能增加的,varchar是变长字符串,其最大是65535个字节

当对其进行插入的时候,发现5个字符能够插入,但是多了就不能够插入了

那么这个变长字符串的变长体现在哪里呢?

如上,当给varchar类型分配空间后,这里是分配了5个字符的空间,但是如果实际插入的字符串长度不足5个,比如说3个,那么就只会只使用3个字符空间,如果实际插入的字符为4个,那么就只会只使用4个字符空间,这里的变长体现在varchar类型中,会根据实际插入的字符串长度,动态分配空间,达到变长的效果

所以varchar类型是指定字符个数的上限的

上面说varchar支持的是65535个字节,那么我们设置一下看看

发现这里是不行的,会发现这里是21845,为什么呢?----- 我们知道这里是存的是中文字符,一个中文字符在utf8编码中占3个字节,那么65535 / 3 = 21845,这就是varchar支持的最大字符串长度

那么我们修改为21845

发现居然又错了,上述报错翻译过来就是:

行大小太大。使用的表类型(不计算 BLOB)的最大行大小为 65535。这包括存储开销,请查看手册。您必须将某些列更改为 TEXT 或 BLOB

实际上,对于中文字符串来说,其空间不仅仅只是记录数据的,还需要1~2个长度标识字节,还有1字节来存储其他控制信息

所以实际上,最长字符串长度为(65535-3)/3=21844

char和varchar区别:

对比维度 CHAR VARCHAR
存储方式 固定长度,填充空格至定义长度 可变长度,存储实际数据+长度标识(1-2字节)
空间占用 固定(定义长度) 动态(实际长度+长度标识)
存取性能 更快(直接定位固定长度) 略慢(需解析长度标识)
最大字符数 255(与字符集无关) 受字符集影响(如utf8:约21844字符)
尾部空格处理 存入时自动补空格,检索时自动去除 保留存入时的尾部空格
适用场景 短且定长的数据(如性别代码、MD5哈希) 长度不定的数据(如用户名、地址)

五、时间日期类型:

常用的时间类型有三种,分别是:

  • date:其格式为YYYY-MM-DD,占用3字节
  • datetime:其格式为YYYY-MM-DD HH:MM:SS,占用8字节
  • timestamp:这是时间戳,其格式为YYYY-MM-DD HH:MM:SS,占用4字节

接着向前两个插入数据:这是比较简单的

但是关于d3,也就是时间戳

从 MySQL 5.6.6 起,

TIMESTAMP列如果没有显式指定DEFAULT值

就不会在自动默认给CURRENT_TIMESTAMP

除非用户明确加上DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP

否则该字段就是普通的NULLABLE列

如果已经创建了,可以用语句:ALTER TABLE t7
MODIFY COLUMN d3 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;来给t7表的d3列加上缺省

这样如果是缺省的TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE就能够当时间戳在更新时就会自动刷新,如update修改数据的时候,但是这里修改表中的列如id,或者这个列的类型是不会刷新时间戳的

如下,t8表

向t8表中插入数据id = 1,这个时候不用管时间戳,他会自动填入的

当对表中的数据进行修改,比如将id的值从1修改为0

这样的话TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE修饰的时间戳就会自动更新,TIMESTAMP DEFAULT CURRENT_TIMESTAMP修饰的时间戳不会自动更新

这里是修改数据才会使其更新,如果修改表中的字段是不会引发更新的,比如将id修改为idd是不会引发更新的

六、enum与set类型:

enum:

enum被称为枚举类型,他是用于提供一批元素,然后只能选择其中的一个

我们创建一个表,其中用枚举表示男或者女

这样,在其中查看

当向其中进行插入的时候,对sex进行插入的时候,只能从其列表中进行选择一个元素进行插入

insert into t9 values ('张三','男');
insert into t9 values ('李四','女');

如果是列表中不存在的,或者是插入多个,都是不可以的 

如果列表中的元素字符特别长,不想打字,那么也可以使用数字插入,从1开始对应着列表中的第一个,往后依次++,在上述案例中,男就是对应的1,女就是对应的2

当然,插入没有对应的数字也是不行的

set:

这个被称为集合类型,是支持多选的,用法和enum差不多

我们可以在创建表的时候进行set类型的创建,也可以对已经创建好的表进行增加

alter table t9 add (drink set('可乐','雪碧','茶π','红牛','阿萨姆'));

当向其中进行插入的时候,对drink进行插入的时候,只能从其列表中可以选择多个元素进行插入

insert into t9 values ('张三','男','可乐,雪碧,红牛');
insert into t9 values ('李四','女','茶π,阿萨姆');

同样,也可以使用数字进行插入

上述插入了12345,感觉像是对应着上述的5中品牌

但是查看的时候:

如上,红框框中是对应着上述的五条语句的,但是发现结果不是预期

这是为什么呢?

实际上,这是类似于二进制的存储方式的

当为1的时候,也就是从小到大加一,然后在倒过来看

当为2的时候,进行+1,然后就是雪碧为1,当倒过来看也就是2

当为3的时候,在进行加1,此时就是11000,倒过来就是00011就是3... 往后以此类推

所以根据上述规律,如果全部都喜欢的话,就是 11111 也就是1 00000 也就是2^5-1也就是31

发现正如我们所料

这里有一个奇怪的,如果我们插入0,那么会发现其对应的不是NULL,而是空,这里NULL和空是不等价的,NULL表示什么都插入,空表示插入了这个类型,他是存在的,但是此时为空

集合中的查询:

查询enum

这个比较简单,因为其是唯一的

在查询的时候直接加上 where sex='女'即可

查询set

如果像查询enum一样,那么查询出来的仅仅是只有一个的

如果我们想查询包含可乐的,就需要借助函数find_in_set(str, strlist)

其作用是查询strlist中是否存在str,如果查询到了,就返回对应位置的下标(注意是从1开始的),如果没查到就返回0

select * from t9 where find_in_set('可乐',drink);

这样就能够查看所有包含可乐的了

如果想查询喜欢可乐和雪碧的,就需要用and连接

select * from t9 where find_in_set('可乐',drink) and find_in_set('雪碧',drink);


网站公告

今日签到

点亮在社区的每一天
去签到