【MYSQL】MYSQL学习的一大重点:MYSQL数据类型

0 ~> int:最佳实践

整数后面的圆括号里的内容我们暂时还不清楚,但是bit后面的圆括号我们知道了,就是:你想带几个bit

sql 复制代码
mysql> show tables; 
Empty set (0.00 sec)

mysql> select database(); 
+------------+
| database() |
+------------+
| d4         |
+------------+
1 row in set (0.00 sec)

mysql> create table if not exists t1(
    -> id int,
    -> online bit(65)
    -> );
ERROR 1439 (42000): Display width out of range for column 'online' (max = 64)
mysql> create table if not exists t1( id int, online bit(64) );
Query OK, 0 rows affected (0.04 sec)

mysql> desc t1;
+--------+---------+------+-----+---------+-------+
| Field  | Type    | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| id     | int     | YES  |     | NULL    |       |
| online | bit(64) | YES  |     | NULL    |       |
+--------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> drop table t1;
Query OK, 0 rows affected (0.02 sec)

mysql> create table if not exists t1( id int, online bit );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t1;
+--------+--------+------+-----+---------+-------+
| Field  | Type   | Null | Key | Default | Extra |
+--------+--------+------+-----+---------+-------+
| id     | int    | YES  |     | NULL    |       |
| online | bit(1) | YES  |     | NULL    |       |
+--------+--------+------+-----+---------+-------+
2 rows in set (0.01 sec)

AI写代码bash
123456789101112131415161718192021222324252627282930313233343536373839404142

1 ~> 数据类型分类

1.1 数值类型

数据类型 说明
BIT(M) 位类型。M指定位数,默认值1,范围1-64
TINYINT UNSIGNED 带符号的范围-128127,无符号范围0255。默认有符号
BOOL 使用0和1表示真和假
SMALLINT UNSIGNED 带符号是-2^15次方 到 215-1,无符号是216-1
INT UNSIGNED 带符号是-2^31次方 到 231-1,无符号是232-1
BIGINT UNSIGNED 带符号是-2^63次方 到 263-1,无符号是264-1
FLOAT (M, D) UNSIGNED M指定显示长度,d指定小数位数,占用4字节
DOUBLE (M, D) UNSIGNED 表示比float精度更大的小数,占用空间8字节
DECIMAL (M, D) UNSIGNED 定点数M指定长度,D表示小数点的位数

1.2 文本、二进制类型

数据类型 说明
CHAR (size) 固定长度字符串,最大255
VARCHAR (SIZE) 可变长度字符串,最大长度65535
BLOB 二进制数据
TEXT 大文本,不支持全文索引,不支持默认值

1.3 时间日期

数据类型 说明
DATE/DATETIME/TIMESTAMP 日期类型(yyyy-mm-dd) (yyyy-mm-dd hh:mm:ss) timestamp时间戳

1.4 String **类型

数据类型 说明
ENUM类型 ENUM是一个字符串对象,其值来自表创建时在列规定中显示枚举的一列值
SET类型 SET是一个字符串对象,可以有零或多个值,其值来自表创建时规定的允许的一列值。指定包括多个set成员的set列值时各成员之间用逗号隔开。这样set成员值本身不能包含逗号。

2 ~> 数值类型

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

2.1 TINYINT 类型

默认有符号,可通过 UNSIGNED 指定无符号。

示例:

sql 复制代码
-- 有符号
mysql> CREATE TABLE ttl (num TINYINT);
mysql> INSERT INTO ttl VALUES(1);
mysql> INSERT INTO ttl VALUES(128);   -- 越界,报错
ERROR 1264 (22003): Out of range value for column 'num' at row 1

-- 无符号
mysql> CREATE TABLE tt2 (num TINYINT UNSIGNED);
mysql> INSERT INTO tt2 VALUES(-1);    -- 越界,报错
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> INSERT INTO tt2 VALUES(255);   -- 成功

AI写代码sql
1234567891011

注意:尽量不要使用 UNSIGNED,因为可能仍然存不下较大数值,不如直接使用更大的类型(如 BIGINT)。

2.2 BIT 类型

语法:BIT[(M)],M 范围 1~64,默认 1。

存储为二进制值,查询时默认按 ASCII 码显示。

sql 复制代码
mysql> CREATE TABLE tt4 (id INT, a BIT(8));
mysql> INSERT INTO tt4 VALUES(10, 10);
mysql> SELECT * FROM tt4;
+------+------+
| id   | a    |
+------+------+
| 10   |      |   -- 10 对应 ASCII 不可见字符,所以显示为空
+------+------+

mysql> INSERT INTO tt4 VALUES(65, 65);
mysql> SELECT * FROM tt4;
+------+------+
| id   | a    |
+------+------+
| 10   |      |
| 65   | A    |   -- 65 对应 ASCII 'A'
+------+------+

AI写代码sql
1234567891011121314151617

如果只存放 0 或 1,可定义为 BIT(1) 以节省空间。

sql 复制代码
mysql> CREATE TABLE tt5 (gender BIT(1));
mysql> INSERT INTO tt5 VALUES(0), (1);
mysql> INSERT INTO tt5 VALUES(2);   -- 越界,报错
ERROR 1406 (22001): Data too long for column 'gender' at row 1

AI写代码sql
1234

2.3 小数类型

2.3.1 FLOAT

  • 语法:FLOAT[(M,D)] [UNSIGNED],M 为显示长度,D 为小数位数,占用 4 字节。
  • 保存时会四舍五入。
sql 复制代码
mysql> CREATE TABLE tt6 (id INT, salary FLOAT(4,2));  -- 范围 -99.99 ~ 99.99
mysql> INSERT INTO tt6 VALUES(100, -99.99);
mysql> INSERT INTO tt6 VALUES(101, -99.991);          -- 四舍五入为 -99.99
mysql> SELECT * FROM tt6;
+------+--------+
| id   | salary |
+------+--------+
| 100  | -99.99 |
| 101  | -99.99 |
+------+--------+

AI写代码sql
12345678910
  • 无符号 FLOAT(4,2) UNSIGNED 范围 0 ~ 99.99。
sql 复制代码
mysql> CREATE TABLE tt7 (id INT, salary FLOAT(4,2) UNSIGNED);
mysql> INSERT INTO tt7 VALUES(100, -0.1);   -- 警告,实际可能变为 0
mysql> INSERT INTO tt7 VALUES(100, 0);
mysql> INSERT INTO tt7 VALUES(100, 99.99);

AI写代码sql
1234

2.3.2 DECIMAL

  • 语法:DECIMAL(M,D) [UNSIGNED],定点数,M 为总位数,D 为小数位数。
  • 例如:DECIMAL(5,2) 范围 -999.99 ~ 999.99,无符号时 0 ~ 999.99。
  • 精度比 FLOAT 高,适合需要精确计算的场景(如金额)。
sql 复制代码
mysql> CREATE TABLE tt8 (id INT, salary FLOAT(10,8), salary2 DECIMAL(10,8));
mysql> INSERT INTO tt8 VALUES(100, 23.12345612, 23.12345612);
mysql> SELECT * FROM tt8;
+------+-------------+-------------+
| id   | salary      | salary2     |
+------+-------------+-------------+
| 100  | 23.12345695 | 23.12345612 |   -- float 出现精度误差,decimal 精确
+------+-------------+-------------+

AI写代码sql
12345678

FLOAT 精度约为 7 位有效数字,DOUBLE 约为 15 位。

DECIMAL 最大位数 M 为 65,小数位数 D 最大为 30。若省略 D,默认为 0;若省略 M,默认为 10。

  • 建议: 对精度要求高的数据使用 DECIMAL。

3 ~> 字符串类型

3.1 CHAR

语法:CHAR(L),L 为字符数,最大 255。

固定长度,存储时右补空格到指定长度,检索时会去掉末尾空格(但严格模式可能保留)。

sql 复制代码
mysql> CREATE TABLE tt9 (id INT, name CHAR(2));
mysql> INSERT INTO tt9 VALUES(100, 'ab');
mysql> INSERT INTO tt9 VALUES(101, '中国');   -- 一个汉字算一个字符
mysql> SELECT * FROM tt9;
+------+------+
| id   | name |
+------+------+
| 100  | ab   |
| 101  | 中国 |
+------+------+

mysql> CREATE TABLE tt10 (id INT, name CHAR(256));   -- 错误,超过最大长度
ERROR 1074 (42000): column length too big for column 'name' (max = 255); use BLOB or TEXT instead

AI写代码sql
12345678910111213

3.2 VARCHAR

语法:VARCHAR(L),L 为字符数,但实际最大长度受字节数限制(最多 65535 字节)。

需要 1~3 字节额外空间记录数据长度,因此可用字节数为 65532。

不同字符集下最大字符数不同:

  • utf8mb4:每个字符最多 4 字节,最大字符数 ≈ 65532 / 4 = 16383。
  • utf8(即utf8mb3):每个字符最多 3 字节,最大字符数 ≈ 65532 / 3 = 21844。
  • gbk:每个字符 2 字节,最大字符数 ≈ 65532 / 2 = 32766。
sql 复制代码
-- utf8 编码下,最大可定义 21844 个字符
mysql> CREATE TABLE ttl (name VARCHAR(21844)) CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

-- 21845 超出限制
mysql> CREATE TABLE ttl (name VARCHAR(21845)) CHARSET=utf8;
ERROR 1118 (42000): Row size too large. ...

AI写代码sql
1234567

3.3 CHAR 与 VARCHAR 对比

假设使用 utf8 字符集(每个字符最多 3 字节),CHAR(4)VARCHAR(4)对比如下:

实际存储内容 CHAR(4) 存储方式(固定占用 4 字节) VARCHAR(4) 存储方式(可变,+1 字节记录长度)
'abcd' 4 个字符(12 字节) 4 个字符 + 1 字节长度 = 13 字节
'A' 1 个字符右补 3 个空格(4 字节) 1 个字符 + 1 字节长度 = 4 字节
'Abcde' 超出长度,插入失败 超出长度,插入失败

4 ~> 日期和时间类型

类型 格式 占用字节 说明
DATE 'yyyy-mm-dd' 3 仅日期
DATETIME 'yyyy-mm-dd HH:ii:ss' 8 日期和时间,范围 1000-01-01 ~ 9999-12-31
TIMESTAMP 'yyyy-mm-dd HH:ii:ss' 4 时间戳,范围 1970-01-01 ~ 2038-01-19
sql 复制代码
-- 创建表
mysql> CREATE TABLE birthday (t1 DATE, t2 DATETIME, t3 TIMESTAMP);

-- 插入数据(t3 自动填充当前时间)
mysql> INSERT INTO birthday (t1, t2) VALUES ('1997-7-1', '2008-8-8 12:1:1');
mysql> SELECT * FROM birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 1997-07-01 | 2008-08-08 12:01:01 | 2023-01-01 12:34:56 |
+------------+---------------------+---------------------+

-- 更新数据时,TIMESTAMP 自动更新为当前时间
mysql> UPDATE birthday SET t1 = '2000-1-1';
mysql> SELECT * FROM birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2000-01-01 | 2008-08-08 12:01:01 | 2023-01-01 12:35:10 |
+------------+---------------------+---------------------+

AI写代码sql
1234567891011121314151617181920

注意: TIMESTAMP 的行为(自动初始化 **和自动更新)可以通过建表时的 DEFAULTON UPDATE 子句控制。


5 ~> ENUM 和 SET

5.1 ENUM(枚举)

单选类型,格式:ENUM('值1', '值2', ...)

实际存储为数字索引(从 1 开始),最多 65535 个选项。

插入时可以使用值本身或数字索引。

5.2 SET(集合)

多选类型,格式:SET('值1', '值2', ...)

实际存储为位图(每个选项对应一个比特位:1,2,4,8,...),最多 64 个选项。

插入时用逗号分隔多个值,如'登山,游泳'

5.3 示例:调查表

sql 复制代码
CREATE TABLE votes (
    username VARCHAR(30),
    hobby SET('登山','游泳','篮球','武术'),   -- 多选
    gender ENUM('男','女')                   -- 单选
);

-- 插入数据
INSERT INTO votes VALUES ('雷锋', '登山,武术', '男');
INSERT INTO votes VALUES ('Juse', '登山,武术', 2);   -- 2 对应 '女'
INSERT INTO votes VALUES ('LiLei', '登山', '男');
INSERT INTO votes VALUES ('LiLei', '篮球', '男');
INSERT INTO votes VALUES ('HanMeiMei', '游泳', '女');

AI写代码sql
123456789101112

5.3.1 查询技巧

直接使用=查询 SET 列只能匹配完全相同的值,无法查找包含某一项的行。

应使用FIND_IN_SET()函数:FIND_IN_SET('登山', hobby)返回非 0 表示存在。

sql 复制代码
-- 错误:只能查出 hobby 正好等于 '登山' 的行
SELECT * FROM votes WHERE hobby = '登山';

-- 正确:查出所有包含 '登山' 的行
SELECT * FROM votes WHERE FIND_IN_SET('登山', hobby);

AI写代码sql
12345
  • 注意: 不建议在插入时直接使用数字编号,因为不利于阅读和维护。
相关推荐
血小溅11 分钟前
Spring AI 对 Skill/MCP 的支持全景整理
后端
晓杰'21 分钟前
从0到1实现Balatro游戏后端(8):Skip Blind与Tag奖励机制设计与实现
后端·websocket·typescript·项目实战·nestjs·状态管理·游戏服务器
叫我:松哥25 分钟前
基于Flask框架的校园二手书籍交易平台,注重校园场景的特殊需求,通过学号认证保障用户真实性
后端·python·sqlite·flask·bootstrap
终将老去的穷苦程序员1 小时前
基于SpringBoot的餐饮管理系统
java·spring boot·后端
北顾笙9801 小时前
MYSQL-day03
数据库·sql·mysql
张忠琳1 小时前
【Go 1.26.4】Golang Map 深度解析
开发语言·后端·golang
ULIi096kr1 小时前
MySQL大表优化终极方案:单表数据量上限、卡顿解决、分表分库实战教程
数据库·mysql
deviant-ART2 小时前
MySQL里的三个concat函数
数据库·mysql
一条泥憨鱼2 小时前
Java开发效率神器:Lombok从入门到精通!
java·后端·学习·开发·lombok
熠熠仔2 小时前
Spring Boot 与 MyBatis-Plus 空间几何数据集成指南
spring boot·后端·mybatis