mysql初阶--数据类型

MySQL 数据类型

本篇笔记系统梳理了 MySQL(SQL)中常用的数据类型,覆盖数值类型、字符串类型、二进制类型、日期时间类型 四大类,逐类给出存储大小、取值范围、精度说明、0 值与典型选型,并补充了 CHAR 与 VARCHAR、VARCHAR 与 TEXT 的对比与选型建议。适合入门到进阶复习,所有要点均可逐条对照课件。

目录

  • [1. 本节目标](#1. 本节目标)
  • [2. 常用数据类型分类](#2. 常用数据类型分类)
  • [3. 数值类型(数据值类型)](#3. 数值类型(数据值类型))
    • [3.1 类型列表](#3.1 类型列表)
    • [3.2 数据类型取值范围](#3.2 数据类型取值范围)
  • [4. 字符串类型](#4. 字符串类型)
    • [4.1 类型列表](#4.1 类型列表)
    • [4.2 关于排序](#4.2 关于排序)
    • [4.3 CHAR 与 VARCHAR 的区别](#4.3 CHAR 与 VARCHAR 的区别)
    • [4.4 如何选择 CHAR 与 VARCHAR](#4.4 如何选择 CHAR 与 VARCHAR)
    • [4.5 VARCHAR 与 TEXT 的区别](#4.5 VARCHAR 与 TEXT 的区别)
  • [5. 二进制类型](#5. 二进制类型)
  • [6. 日期与时间类型](#6. 日期与时间类型)
    • [6.1 类型列表](#6.1 类型列表)
    • [6.2 其他](#6.2 其他)
  • [7. 选型总结](#7. 选型总结)

1. 本节目标

  • 掌握数据类型分类:理解 SQL 中数据类型的整体划分(数值、字符串、二进制、日期),以及它们各自对应的应用场景。
  • 掌握常用数据类型:熟悉每一种常用类型的存储大小、取值范围与精度,能在建表时为字段选择合适的类型。

2. 常用数据类型分类

在面向对象软件开发的过程中,通常会先进行需求分析 从而得到类 和属性。这套概念可以一一映射到数据库的世界中:

面向对象 关系数据库
类(Class) 实体(Entity,通常以表的形式存在)
属性(Attribute) 实体中的属性(即表中的字段 / 列)
------ 每个实体对应一张表
对象实例 表中的一条记录(数据行),即实体的一个实例

一条记录包含若干字段(列),每个字段代表实体的一个属性。

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

  • 数值类型(数据值类型):整数、浮点数、精确小数。
  • 字符串类型:定长 / 变长字符串、文本类型、枚举与集合。
  • 二进制类型:用于存储二进制字节(图片、文件等)。
  • 日期类型:日期、时间、日期时间、时间戳、年份。

3. 数值类型(数据值类型)

3.1 类型列表

类型 大小 说明
BIT[(M)] 默认 1 bit 位值类型 。M 表示每个值的位数,取值范围 1 ~ 64 。若省略 M,默认为 1。
TINYINT[(M)] 1 byte 取值范围 -2⁷ ~ 2⁷−1 (即 -128 ~ 127);无符号取值范围 0 ~ 2⁸−1(即 0 ~ 255)。
BOOL / BOOLEAN 1 byte TINYINT(1) 的同义词。值为 0 被视为假(false) ,非 0 值被视为真(true)。
SMALLINT[(M)] 2 byte 取值范围 -2¹⁵ ~ 2¹⁵−1 ;无符号取值范围 0 ~ 2¹⁶−1。
MEDIUMINT[(M)] 3 byte 取值范围 -2²³ ~ 2²³−1 ;无符号取值范围 0 ~ 2²⁴−1。
INT[(M)] 4 byte 取值范围 -2³¹ ~ 2³¹−1 ;无符号取值范围 0 ~ 2³²−1。
INTEGER[(M)] 4 byte INT[(M)] 的同义词。
BIGINT[(M)] 8 byte 取值范围 -2⁶³ ~ 2⁶³−1 ;无符号取值范围 0 ~ 2⁶⁴−1。
FLOAT[(M,D)] 4 byte 单精度浮点型 。M 是总位数,D 是小数点后面的位数,大约可精确到小数点后 7 位。
DOUBLE[(M,D)] 8 byte 双精度浮点型 。M 是总位数,D 是小数点后面的位数,大约可精确到小数点后 15 位。
DECIMAL[(M[,D])] 动态 不存在精度损失 (以字符串形式保存的精确数值)。M 是总位数,D 是小数点后的位数。最大位数(M)为 65 ,最大小数位数(D)为 30 。若省略 M 默认为 10 ;若省略 D 默认为 0 。M 中不计算小数点和负号 - ;若 D 为 0,则值没有小数点和小数部分。

💡 补充说明(关于 INT(M) 中的 M) :在 MySQL 8.0 之后,整数类型括号里的 M(如 INT(11))只表示显示宽度 ,不再影响取值范围 ,且对 SELECT 输出的实际取值没有任何限制作用,仅为历史遗留写法。真正决定存储与取值范围的是类型本身(TINYINT / INT / BIGINT......)以及是否 UNSIGNED。
💡 选型经验 :表示状态、布尔值优先 TINYINT;普通整数用 INT;金额、需要精确计算的小数(如财务)务必使用 DECIMAL,不要用 FLOAT / DOUBLE,因为浮点数存在精度损失。

3.2 数据类型取值范围

类型 大小 有符号最小值 有符号最大值 无符号最小值 无符号最大值
TINYINT 1 Byte -128 127 0 255
SMALLINT 2 Byte -32768 32767 0 65535
MEDIUMINT 3 Byte -8388608 8388607 0 16777215
INT 4 Byte -2147483648 2147483647 0 4294967295
BIGINT 8 Byte -2⁶³ 2⁶³−1 0 2⁶⁴−1

规律:有符号 类型占用 n 字节时,取值范围为 -2^(8n-1) ~ 2^(8n-1)−1 ;加上 UNSIGNED 后范围为 0 ~ 2^(8n)−1 。可见 UNSIGNED 把"负数那半边"的空间全部让给了正数,使正数上限翻倍。


4. 字符串类型

4.1 类型列表

字符串(以字符为单位)

类型 说明
CHAR[(M)] 固定长度 字符串。M 表示长度,以字符为单位 ,取值范围 0 ~ 255 ;M 省略则长度为 1。
VARCHAR(M) 可变长度 字符串。M 表示字符最大长度,取值范围 0 ~ 65535 ;有效字符个数取决于实际字符数 和使用的字符集。
TINYTEXT 小文本类型,最大长度为 255(2⁸−1)个字节,有效字符个数取决于字符集。
TEXT[(M)] 文本类型,最大长度为 65535(2¹⁶−1)个字节,有效字符个数取决于字符集。
MEDIUMTEXT 中文本类型,最大长度为 16,777,215(2²⁴−1)个字节,有效字符个数取决于字符集。
LONGTEXT 大文本类型,最大长度为 4,294,967,295(即 4GB,2³²−1)个字节,有效字符个数取决于字符集。

枚举与集合

类型 说明
ENUM('value1','value2',...) 枚举 。从值列表 'value1','value2' 或 ''(空字符串)以及 NULL 中选一个值 ;最多可有 65,535 个不同元素;单个元素最大长度受 M ≤ 255 或 (M × w) ≤ 1020 限制(M 是元素字符长度,w 是字符集中字符所需的最大字节数);ENUM 的值在内部表示为整数。
SET('value1','value2',...) 集合 。从值列表 'value1','value2' 中选零个或多个值 ;最多 64 个元素;单个元素最大长度同样受 M ≤ 255 或 (M × w) ≤ 1020 限制;SET 值在内部表示为整数。

💡 ENUM vs SET :ENUM 是"多选一"(如性别:男 / 女 / 未知);SET 是"多选多 / 子集"(如标签集合:可同时拥有多个标签)。两者内部都以整数存储,因此占空间小、比较与排序快 ,但取值只能来自预先定义的列表,灵活性较低。
💡 CHAR/VARCHAR vs TEXT :前者是"短字符串",后者是"长文本"。当 TEXT 实际长度需求超过阈值时,MySQL 会自动升级为更大的文本类型(详见 4.5)。

4.2 关于排序

  • 字符串类型的列以字符为单位 ,并且可以为列单独指定字符集和排序规则 。例如:字符集为 utf8mb4,排序规则为 utf8_0900_ai_ci(其中 ci 表示 case-insensitive,大小写不敏感)。
  • 二进制的列以字节为单位 ,可以指定以 _bin 结尾的排序规则,例如 utf8mb4_bin。此时比较和排序基于数字字符的代码值(逐字节比较) ,因此是大小写敏感的。

4.3 CHAR 与 VARCHAR 的区别

  • CHAR 固定长度字符串

    • M 表示以字符为单位 的列长度,取值范围 0 ~ 255,省略则长度为 1。
    • 存储时总是用空格向右填充 到指定长度;获取列的值时会从尾部删除空格。
    • 允许定义 CHAR(0),此时列的值只能为 NULL 或空字符串,主要目的是兼容旧系统------例如某个类中必须有这个属性,但又不使用它的值(值没有实际意义,但列不能不存在)。
  • VARCHAR 可变长度字符串

    • M 表示以字符为单位 的最大列长度,取值范围 0 ~ 65,535(在所有列中共享)。
    • 有效长度取决于实际字符数 和使用的字符集。
    • 用额外的一或两个字节 记录实际使用的字节数:当实际字节数不超过 255 个字节 时用一个字节记录长度;超过 255 个字节时使用两个字节记录长度。
    • 获取列的值时不会从尾部删除空格 ;插入数据时会删除超出长度的尾部空格。

示例:观察尾部空格的差异

sql 复制代码
mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO vc VALUES ('ab  ', 'ab  ');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+
| CONCAT('(', v, ')') | CONCAT('(', c, ')') |
+---------------------+---------------------+
| (ab  )              | (ab)                |
+---------------------+---------------------+
1 row in set (0.06 sec)

mysql> INSERT INTO vc VALUES ('ab    ', 'ab  ');
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------------------+
| Level | Code | Message                                |
+-------+------+----------------------------------------+
| Note  | 1265 | Data truncated for column 'v' at row 1 |
+-------+------+----------------------------------------+
1 row in set (0.00 sec)

解读:

  • 第一行插入 'ab '(ab 后两个空格)时,CHAR(4) 列 c 在存储时被空格右填充到 4 位,但查询时尾部空格被删除,所以 CONCAT('(', c, ')') 输出 (ab);而 VARCHAR(4) 列 v 会保留 尾部空格,输出 (ab )。
  • 第二行插入 'ab '(超出 VARCHAR(4) 的有效长度)时,会触发 Data truncated 警告(Note 1265),超出的空格被截断。

💡 一句话记忆:CHAR 存时补空格、取时去空格;VARCHAR 存时按实际长度、取时不去空格。

4.4 如何选择 CHAR 与 VARCHAR

  • 如果数据长度基本都一样 ,使用定长 CHAR,例如:身份证号、MD5 值、学号、邮编。
  • 如果数据长度有变化 ,使用变长 VARCHAR,例如:名字、地址 ,但要规划好长度,保证最长的字符串能存进去。
  • 定长 CHAR 比较浪费磁盘空间,但效率高 ------它会直接开辟好对应的存储空间,无需额外记录实际长度。
  • 变长 VARCHAR 比较节省磁盘空间,但效率略低 ------它在不超过定义长度范围的情况下用多少开辟多少存储空间。

💡 经验补充:定长字段往往更适合做索引与比较(无变长带来的指针与长度计算开销),因此短、等长、高频检索 的字段倾向 CHAR;长、不等长、存储优先 的字段倾向 VARCHAR。

4.5 VARCHAR 与 TEXT 的区别

  • 容量大小 :VARCHAR 最大支持 65535 个字节 ;TEXT 最大支持 65535 个字节 。在指定 TEXT 长度时,当超过 65535 时自动转换为 MEDIUMTEXT,当超过 16,777,215 时自动转换为 LONGTEXT。
  • 存储位置 :VARCHAR 类型的列,实际内容小于 768 字节时存在当前行 ,大于 768 时存在溢出页 ,当前行保存溢出页的地址;TEXT 类型的列整体保存在溢出页,当前行只保存溢出页地址。
  • 查询性能 :对于频繁查询的 VARCHAR 列可以创建索引 ,提升查询性能;TEXT 类型的列无法直接创建普通索引 ,但可以使用 FULLTEXT 索引。由于索引的支持与存储位置不同,VARCHAR 列的性能高于 TEXT 列。
  • 适用场景 :如果存储的数据长度较小且需要创建索引进行检索 ,可选择 VARCHAR,如姓名、用户名、邮箱 等;如果存储的数据长度较大且不需要频繁以该列为条件检索 ,可选择 TEXT,如文章内容等。

5. 二进制类型

二进制类型以字节为单位 存储二进制字节序列,常用于存储图片、文件、加密后的密文等二进制数据。它与字符串类型的差别在于:存储的是二进制字节而不是字符 ,不做字符集与大小写排序处理,比较排序基于字节值。

类型 说明
BINARY[(M)] 固定长度二进制字节 ,与 CHAR 类似,但存储的是二进制字节 而不是字符串。M 表示长度,以字节为单位 ,取值范围 0 ~ 255 ;M 省略则长度为 1。
VARBINARY(M) 可变长度二进制字节 ,与 VARCHAR 类似,但存储的是二进制字节 而不是字符串。M 表示长度,以字节为单位。
TINYBLOB 小二进制字节类型,最大长度为 255(2⁸−1)个字节。
BLOB[(M)] 二进制字节类型,最大长度为 65535(2¹⁶−1)个字节。
MEDIUMBLOB 中二进制字节类型,最大长度为 16,777,215(2²⁴−1)个字节。
LONGBLOB 大二进制字节类型,最大长度为 4,294,967,295(即 4GB,2³²−1)个字节。

💡 BLOB 系列与 TEXT 系列一一对应 :TINYBLOB↔TINYTEXT、BLOB↔TEXT、MEDIUMBLOB↔MEDIUMTEXT、LONGBLOB↔LONGTEXT,最大长度完全相同;唯一的区别是 BLOB 存二进制字节、TEXT 存字符。


6. 日期与时间类型

6.1 类型列表

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

⚠️ 勘误提示 :课件中 TIMESTAMP 上限曾误写为 "20388-01-19",正确应为 2038-01-19 03:14:07 ;LONGBLOB 的 4GB 对应的是 2³²−1(课件中误写为 2⁸−1),此处已更正。
💡 TIMESTAMP vs DATETIME(高频考点):

  • TIMESTAMP 只占 4 字节 、范围窄(受 2038 年问题 限制),并且会与时区绑定:写入时按当前时区转成 UTC 存储、读出时再转回会话时区。
  • DATETIME 占 8 字节 、范围宽(1000 ~ 9999 年),与时区无关,存什么读什么。
  • 选型:需要跨时区、自动记录"创建/修改时间"用 TIMESTAMP;需要大范围、稳定的字面日期时间用 DATETIME。

6.2 其他

  • fsp 为可选设置 ,用来指定小数秒精度 ,范围 0 ~ 6;值为 0 表示没有小数部分;若省略,默认精度为 0。
  • CURRENT_DATE 和 CURRENT_DATE() 是 CURDATE() 的同义词,用于获取当前日期。
  • CURRENT_TIME 和 CURRENT_TIME([fsp]) 是 CURTIME() 的同义词,用于获取当前时间。
  • CURRENT_TIMESTAMP 和 CURRENT_TIMESTAMP([fsp]) 是 NOW() 的同义词,用于获取当前日期和时间。
sql 复制代码
-- 一个常用的小例子:建表时自动维护创建/更新时间
CREATE TABLE article (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title       VARCHAR(120) NOT NULL,          -- 标题:变长字符串
    content     LONGTEXT,                        -- 正文:长文本,用 LONGTEXT
    author      CHAR(18) ,                       -- 身份证:定长,用 CHAR
    status      ENUM('draft','published','archived') DEFAULT 'draft', -- 状态:多选一
    tags        SET('java','mysql','python'),    -- 标签:多选多
    created_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,                 -- 创建时间
    updated_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 更新时间
);

7. 选型总结

要存什么 推荐类型 理由
状态 / 布尔 TINYINT / BOOL 仅 1 字节,0/非 0 表真假
普通整数 INT 4 字节,范围足够
超大整数(如雪花 ID) BIGINT 8 字节,范围最大
金额 / 精确小数 DECIMAL 无精度损失,避免浮点误差
等长短字符串(身份证、MD5、邮编) CHAR 定长,效率更高
不定长短字符串(姓名、地址、邮箱) VARCHAR 变长,节省空间
大段文本(文章内容) TEXT / LONGTEXT 容量大,存于溢出页
二进制(图片 / 文件) BLOB / LONGBLOB 以字节存二进制内容
多选一状态 ENUM 内部整数,省空间、快
多选多标签 SET 内部整数,可取子集
跨时区 / 自动时间戳 TIMESTAMP 4 字节,绑定时区
大范围稳定日期时间 DATETIME 范围宽,与时区无关

核心心法 :选型时同时权衡三件事------取值范围够不够 、是否要建索引检索 、是存字符还是二进制 。在满足范围的前提下,用空间更小的类型、能定长则定长、能建索引则建索引,就能兼顾准确与性能。
至此,MySQL 四大类常用数据类型(数值、字符串、二进制、日期时间 )已全部梳理完毕。建议结合建表语句反复对照每种类型的大小、范围、0 值与适用场景,做到"看到一个字段就能条件反射地选出最合适的类型"。

相关推荐
StarsGreen13 分钟前
Android 启动流程详解
android·linux·单片机·嵌入式硬件
Risehuxyc29 分钟前
MySQL密码插件
数据库·mysql
腾科IT教育1 小时前
Oracle考试全解析:OCP、OCM认证体系与核心考点备考指南
数据库·oracle·开闭原则
叼烟扛炮11 小时前
Linux 学习笔记(五十六):IO 多路复用初探——select 的“三宗罪”
linux·服务器·数据库·笔记·学习·php
.痞老板.13 小时前
mysql初阶--数据库基础
数据库·mysql
城北徐宫14 小时前
MySQL约束条件一览
数据库·mysql
码农小河6614 小时前
基于SSM+JSP+MySQL的在线医疗服务系统的设计与实现
java·开发语言·mysql
ClouGence16 小时前
数据库变更审批困局,被这个开源工具解决了
数据库·开源
TDengine (老段)17 小时前
TDengine IDMP 十大实用功能(9)
大数据·数据库·人工智能·物联网·时序数据库·tdengine·idmp