MySQL数据类型 #

一、数据类型概述 #

1.1 类型分类 #

text
MySQL数据类型
├── 数值类型
│   ├── 整数类型
│   │   ├── TINYINT
│   │   ├── SMALLINT
│   │   ├── MEDIUMINT
│   │   ├── INT
│   │   └── BIGINT
│   ├── 浮点类型
│   │   ├── FLOAT
│   │   └── DOUBLE
│   └── 定点类型
│       └── DECIMAL
├── 字符串类型
│   ├── CHAR
│   ├── VARCHAR
│   ├── TEXT系列
│   └── BLOB系列
├── 日期时间类型
│   ├── DATE
│   ├── TIME
│   ├── DATETIME
│   ├── TIMESTAMP
│   └── YEAR
├── JSON类型
│   └── JSON
└── 其他类型
    ├── BOOLEAN
    ├── ENUM
    └── SET

二、整数类型 #

2.1 整数类型列表 #

类型 字节 有符号范围 无符号范围
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 -2^63 ~ 2^63-1 0 ~ 2^64-1

2.2 整数类型使用 #

sql
-- 创建表
CREATE TABLE integers (
    tiny_col TINYINT,
    small_col SMALLINT,
    medium_col MEDIUMINT,
    int_col INT,
    bigint_col BIGINT
);

-- 有符号整数(默认)
CREATE TABLE signed_int (
    num INT
);

-- 无符号整数
CREATE TABLE unsigned_int (
    num INT UNSIGNED
);

-- 显示宽度(不影响存储范围)
CREATE TABLE display_width (
    num INT(5) ZEROFILL
);

INSERT INTO display_width VALUES (123);
-- 查询结果:00123

2.3 选择建议 #

场景 推荐类型
年龄 TINYINT UNSIGNED
状态标识 TINYINT
数量、计数 INT
主键ID INT 或 BIGINT
金额(分) BIGINT

三、浮点类型 #

3.1 浮点类型列表 #

类型 字节 说明
FLOAT 4 单精度浮点数
DOUBLE 8 双精度浮点数

3.2 浮点类型使用 #

sql
-- FLOAT类型
CREATE TABLE float_table (
    price FLOAT,
    weight FLOAT(5,2)
);

-- FLOAT(M,D)
-- M:总位数,D:小数位数
-- FLOAT(5,2):最多5位,小数2位,如:123.45

INSERT INTO float_table VALUES (123.456, 123.45);
-- price存储:约123.456(可能有精度损失)
-- weight存储:123.45

-- DOUBLE类型
CREATE TABLE double_table (
    precise_value DOUBLE(10,6)
);

INSERT INTO double_table VALUES (123.456789);
-- 存储:123.456789

3.3 浮点精度问题 #

sql
-- 浮点数精度问题
SELECT 0.1 + 0.2 = 0.3;  -- 结果:0(false)

-- 原因:浮点数存储有精度损失
SELECT 0.1 + 0.2;  -- 结果:0.30000000000000004

-- 对于精确计算,使用DECIMAL
SELECT CAST(0.1 AS DECIMAL(10,1)) + CAST(0.2 AS DECIMAL(10,1)) = 0.3;
-- 结果:1(true)

四、定点类型 #

4.1 DECIMAL类型 #

sql
-- DECIMAL(M,D)
-- M:精度,总位数(1-65)
-- D:标度,小数位数(0-30)

CREATE TABLE decimal_table (
    amount DECIMAL(10,2),
    rate DECIMAL(5,4)
);

INSERT INTO decimal_table VALUES (12345678.90, 0.1234);

-- 精确计算
SELECT amount * rate FROM decimal_table;
-- 结果:1524156.751926(精确)

4.2 金额存储 #

sql
-- 推荐方案1:DECIMAL存储
CREATE TABLE orders (
    id INT PRIMARY KEY,
    amount DECIMAL(10,2)  -- 单位:元
);

-- 推荐方案2:整数存储(分)
CREATE TABLE orders (
    id INT PRIMARY KEY,
    amount BIGINT  -- 单位:分,12345表示123.45元
);

-- 查询时转换
SELECT amount / 100 AS amount_yuan FROM orders;

五、字符串类型 #

5.1 CHAR和VARCHAR #

类型 说明 最大长度 特点
CHAR(N) 定长字符串 255 不足补空格
VARCHAR(N) 变长字符串 65535 按实际存储
sql
-- CHAR类型
CREATE TABLE char_table (
    code CHAR(10),
    status CHAR(1)
);

INSERT INTO char_table VALUES ('ABC', 'A');
-- code存储:'ABC       '(补空格到10位)

-- VARCHAR类型
CREATE TABLE varchar_table (
    name VARCHAR(100),
    description VARCHAR(500)
);

INSERT INTO varchar_table VALUES ('John', 'This is a description');
-- name存储:'John'(4字节)

5.2 TEXT类型 #

类型 最大长度 存储需求
TINYTEXT 255字节 1字节前缀
TEXT 65535字节 2字节前缀
MEDIUMTEXT 16MB 3字节前缀
LONGTEXT 4GB 4字节前缀
sql
CREATE TABLE articles (
    id INT PRIMARY KEY,
    title VARCHAR(200),
    summary TEXT,
    content LONGTEXT
);

-- TEXT类型不能有默认值
-- 错误:content TEXT DEFAULT ''

5.3 BLOB类型 #

类型 最大长度 说明
TINYBLOB 255字节 小型二进制
BLOB 65KB 二进制大对象
MEDIUMBLOB 16MB 中型二进制
LONGBLOB 4GB 大型二进制
sql
CREATE TABLE files (
    id INT PRIMARY KEY,
    file_name VARCHAR(100),
    file_data MEDIUMBLOB,
    file_size INT
);

-- 存储图片、文件等二进制数据

5.4 字符串类型选择 #

场景 推荐类型
固定长度(如手机号) CHAR
变长字符串 VARCHAR
长文本 TEXT
二进制文件 BLOB

六、日期时间类型 #

6.1 日期时间类型列表 #

类型 格式 范围 字节
DATE YYYY-MM-DD 1000-01-01 ~ 9999-12-31 3
TIME HH:MM:SS -838:59:59 ~ 838:59:59 3
DATETIME YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 8
TIMESTAMP YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 4
YEAR YYYY 1901 ~ 2155 1

6.2 DATE类型 #

sql
CREATE TABLE date_table (
    birth_date DATE,
    event_date DATE
);

INSERT INTO date_table VALUES ('1990-05-15', '2024-12-31');

-- 使用函数
INSERT INTO date_table VALUES (CURRENT_DATE, CURDATE());

-- 日期格式
SELECT DATE_FORMAT(birth_date, '%Y年%m月%d日') FROM date_table;
-- 结果:1990年05月15日

6.3 TIME类型 #

sql
CREATE TABLE time_table (
    start_time TIME,
    duration TIME
);

INSERT INTO time_table VALUES ('09:30:00', '08:00:00');

-- 时间范围可以超过24小时(表示时长)
INSERT INTO time_table VALUES ('100:00:00', '200:30:00');

-- 使用函数
INSERT INTO time_table VALUES (CURRENT_TIME, NOW());

6.4 DATETIME类型 #

sql
CREATE TABLE datetime_table (
    created_at DATETIME,
    updated_at DATETIME
);

INSERT INTO datetime_table VALUES ('2024-01-15 10:30:00', NOW());

-- 自动初始化
CREATE TABLE auto_datetime (
    id INT PRIMARY KEY,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

INSERT INTO auto_datetime (id) VALUES (1);
-- created_at和updated_at自动设置为当前时间

UPDATE auto_datetime SET id = 2 WHERE id = 1;
-- updated_at自动更新为当前时间

6.5 TIMESTAMP类型 #

sql
CREATE TABLE timestamp_table (
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- TIMESTAMP特点:
-- 1. 自动转换为UTC存储
-- 2. 查询时转换为当前时区
-- 3. 范围受限(到2038年)

-- 查看时区设置
SHOW VARIABLES LIKE '%time_zone%';

-- 设置时区
SET time_zone = '+8:00';  -- 东八区
SET time_zone = 'SYSTEM'; -- 系统时区

6.6 YEAR类型 #

sql
CREATE TABLE year_table (
    birth_year YEAR,
    publish_year YEAR(4)
);

INSERT INTO year_table VALUES (1990, 2024);

-- YEAR支持2位或4位
-- 2位年份:00-69转换为2000-2069,70-99转换为1970-1999
INSERT INTO year_table VALUES (24, 99);
-- 存储:2024, 1999

6.7 日期函数 #

sql
-- 当前日期时间
SELECT NOW(), CURRENT_TIMESTAMP, SYSDATE();
SELECT CURDATE(), CURRENT_DATE;
SELECT CURTIME(), CURRENT_TIME;

-- 日期计算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);     -- 加7天
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH);   -- 减1个月
SELECT DATEDIFF('2024-12-31', '2024-01-01'); -- 计算天数差

-- 提取部分
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
SELECT HOUR(NOW()), MINUTE(NOW()), SECOND(NOW());
SELECT WEEKDAY(NOW());  -- 星期几(0=周一)

七、JSON类型 #

7.1 JSON类型特点 #

sql
CREATE TABLE json_table (
    id INT PRIMARY KEY,
    data JSON
);

-- 插入JSON数据
INSERT INTO json_table VALUES (
    1,
    '{"name": "John", "age": 30, "skills": ["MySQL", "Python"]}'
);

-- 插入JSON数组
INSERT INTO json_table VALUES (
    2,
    '[{"id": 1, "name": "A"}, {"id": 2, "name": "B"}]'
);

7.2 JSON函数 #

sql
-- 提取值
SELECT data->'$.name' FROM json_table WHERE id = 1;
SELECT data->>'$.name' FROM json_table WHERE id = 1;  -- 去掉引号

-- JSON_EXTRACT函数
SELECT JSON_EXTRACT(data, '$.name') FROM json_table;

-- 提取数组元素
SELECT data->'$.skills[0]' FROM json_table WHERE id = 1;

-- 创建JSON
SELECT JSON_OBJECT('name', 'John', 'age', 30);
-- 结果:{"name": "John", "age": 30}

SELECT JSON_ARRAY(1, 2, 3, 'a', 'b');
-- 结果:[1, 2, 3, "a", "b"]

-- 合并JSON
SELECT JSON_MERGE_PRESERVE(
    '{"a": 1}',
    '{"b": 2}'
);
-- 结果:{"a": 1, "b": 2}

-- 设置值
UPDATE json_table 
SET data = JSON_SET(data, '$.email', 'john@example.com')
WHERE id = 1;

-- 删除值
UPDATE json_table 
SET data = JSON_REMOVE(data, '$.age')
WHERE id = 1;

7.3 JSON查询 #

sql
-- 按JSON字段查询
SELECT * FROM json_table WHERE data->'$.name' = '"John"';

-- 使用JSON_CONTAINS
SELECT * FROM json_table 
WHERE JSON_CONTAINS(data->'$.skills', '"MySQL"');

-- 使用JSON_SEARCH
SELECT * FROM json_table 
WHERE JSON_SEARCH(data, 'one', 'John') IS NOT NULL;

八、枚举和集合 #

8.1 ENUM类型 #

sql
CREATE TABLE enum_table (
    id INT PRIMARY KEY,
    status ENUM('active', 'inactive', 'pending'),
    priority ENUM('low', 'medium', 'high') DEFAULT 'medium'
);

INSERT INTO enum_table (id, status) VALUES (1, 'active');

-- ENUM存储为整数索引
-- 'active'=1, 'inactive'=2, 'pending'=3

-- 查询索引值
SELECT status + 0 FROM enum_table;

-- 查询所有可能值
SELECT DISTINCT status FROM enum_table;

-- 使用数字插入
INSERT INTO enum_table (id, status) VALUES (2, 2);  -- 'inactive'

8.2 SET类型 #

sql
CREATE TABLE set_table (
    id INT PRIMARY KEY,
    tags SET('tag1', 'tag2', 'tag3', 'tag4')
);

-- 可以存储多个值
INSERT INTO set_table VALUES (1, 'tag1,tag2');
INSERT INTO set_table VALUES (2, 'tag1,tag2,tag3');

-- 使用FIND_IN_SET查询
SELECT * FROM set_table WHERE FIND_IN_SET('tag1', tags) > 0;

-- 使用位运算
SELECT * FROM set_table WHERE tags & 1;  -- 包含tag1

九、布尔类型 #

9.1 BOOLEAN类型 #

sql
-- BOOLEAN是TINYINT(1)的别名
CREATE TABLE bool_table (
    id INT PRIMARY KEY,
    is_active BOOLEAN,
    is_deleted BOOLEAN DEFAULT FALSE
);

INSERT INTO bool_table (id, is_active) VALUES (1, TRUE);
INSERT INTO bool_table (id, is_active) VALUES (2, FALSE);

-- 查询
SELECT * FROM bool_table WHERE is_active = TRUE;
SELECT * FROM bool_table WHERE is_active IS TRUE;
SELECT * FROM bool_table WHERE is_active;

十、类型转换 #

10.1 隐式转换 #

sql
-- 字符串转数字
SELECT '123' + 0;  -- 结果:123
SELECT '123abc' + 0;  -- 结果:123

-- 数字转字符串
SELECT CONCAT(123, 'abc');  -- 结果:'123abc'

-- 日期转换
SELECT '2024-01-01' + INTERVAL 1 DAY;

10.2 显式转换 #

sql
-- CAST函数
SELECT CAST('123' AS SIGNED);
SELECT CAST('123.45' AS DECIMAL(10,2));
SELECT CAST(123 AS CHAR);
SELECT CAST(NOW() AS DATE);

-- CONVERT函数
SELECT CONVERT('123', SIGNED);
SELECT CONVERT('abc' USING utf8mb4);

-- 常用转换
SELECT 
    CAST('2024-01-15' AS DATE),
    CAST('10:30:00' AS TIME),
    CAST('2024-01-15 10:30:00' AS DATETIME);

十一、类型选择建议 #

11.1 数值类型选择 #

场景 推荐类型
主键 INT / BIGINT
年龄 TINYINT UNSIGNED
数量 INT
金额 DECIMAL
科学计算 DOUBLE

11.2 字符串类型选择 #

场景 推荐类型
手机号 CHAR(11)
邮箱 VARCHAR(100)
用户名 VARCHAR(50)
文章内容 TEXT
文件数据 BLOB

11.3 时间类型选择 #

场景 推荐类型
出生日期 DATE
创建时间 DATETIME / TIMESTAMP
时区敏感 TIMESTAMP
持续时间 TIME
年份 YEAR

十二、总结 #

数据类型选择要点:

类型 选择原则
整数 根据范围选择最小类型
小数 精确计算用DECIMAL
字符串 定长用CHAR,变长用VARCHAR
日期 考虑时区和范围
JSON 灵活数据结构

下一步,让我们学习数据库操作!

最后更新:2026-03-26