1、数据类型
MitSeek 发布于 阅读:36
MySQL支持的数据类型
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。
·INTEGER 4字节
这是INT的同义词。
·BIGINT 8字节
大整数。带符号的范围是-9223372036854775808到9223372036854775807。无符号的范围是0到18446744073709551615。
有3种浮点类型是 FLOAT DOUBLE DECIMAC类型。
FLOAT数值类型用于表示单精度浮点数值
DOUBLE数值类型用于表示双精度浮点数值
字符串类型
1. 字符串类型概览
MySQL 提供了多种字符串类型,主要分为三大类:
文本字符串:CHAR, VARCHAR, TEXT 系列
二进制字符串:BINARY, VARBINARY, BLOB 系列
特殊类型:ENUM, SET
2. CHAR 和 VARCHAR
CHAR - 定长字符串
sql
-- 语法
CHAR(M)
-- M 表示字符数,范围 0-255,默认 1
-- 示例
CREATE TABLE users (
id INT,
gender CHAR(1), -- 存储 'M' 或 'F'
country_code CHAR(2), -- 存储 'US', 'CN' 等
fixed_code CHAR(5) -- 总是占用5字符空间
);
-- 特点
- 固定长度,不足部分用空格填充
- 检索时会去掉尾部空格
- 适合存储长度固定的数据(MD5、邮编、状态码)
VARCHAR - 变长字符串
-- 语法
VARCHAR(M)
-- M 表示最大字符数,范围 0-65535
-- 示例
CREATE TABLE articles (
id INT,
title VARCHAR(100), -- 最大100字符
excerpt VARCHAR(255), -- 最大255字符
author_name VARCHAR(50) -- 最大50字符
);
-- 特点
- 可变长度,只占用实际数据长度+1或2字节(长度信息)
- 保留尾部空格
- 适合存储长度变化大的数据
CHAR vs VARCHAR 对比
特性 CHAR VARCHAR
存储方式 固定长度 可变长度
尾部空格 自动去除 保留
存储效率 定长数据高效 变长数据高效
最大长度 255字符 65535字符
适用场景 邮编、代码、标识 姓名、标题、描述
3. TEXT 系列
各种TEXT类型
-- 创建示例表
CREATE TABLE blog_posts (
id INT,
title VARCHAR(255),
summary TINYTEXT, -- 255字符
content TEXT, -- 65,535字符
long_content MEDIUMTEXT, -- 16,777,215字符
book_content LONGTEXT -- 4,294,967,295字符
);
-- 插入数据
INSERT INTO blog_posts VALUES
(1, '文章标题', '简短摘要', '正文内容...', '很长的内容...', '非常非常长的内容...');
TEXT类型比较
类型 最大长度 存储需求 适用场景
TINYTEXT 255字节 L+1字节 简短描述、摘要
TEXT 65,535字节 L+2字节 文章内容、评论
MEDIUMTEXT 16,777,215字节 L+3字节 长篇内容、日志
LONGTEXT 4,294,967,295字节 L+4字节 书籍、大型文档
4. BINARY 和 VARBINARY
二进制字符串类型
sql
-- BINARY - 定长二进制
CREATE TABLE binary_data (
id INT,
token BINARY(16), -- 固定16字节,如UUID
hash BINARY(32) -- 固定32字节,如SHA256
);
-- VARBINARY - 变长二进制
CREATE TABLE variable_binary (
id INT,
image_data VARBINARY(8000), -- 最大8000字节
file_data VARBINARY(16000) -- 最大16000字节
);
5. BLOB 系列
二进制大对象
sql
-- 创建BLOB表
CREATE TABLE file_storage (
id INT,
small_file TINYBLOB, -- 最大255字节
normal_file BLOB, -- 最大65KB
medium_file MEDIUMBLOB, -- 最大16MB
large_file LONGBLOB -- 最大4GB
);
-- 使用示例(在应用程序中处理)
-- 通常用于存储图片、文件、序列化数据等
BLOB类型比较
类型 最大长度 存储需求 适用场景
TINYBLOB 255字节 L+1字节 小图标、缩略图
BLOB 65,535字节 L+2字节 普通图片、文档
MEDIUMBLOB 16,777,215字节 L+3字节 高清图片、音频
LONGBLOB 4,294,967,295字节 L+4字节 视频、大型文件
6. ENUM 和 SET
ENUM - 枚举类型
sql
-- 创建ENUM字段
CREATE TABLE products (
id INT,
name VARCHAR(100),
size ENUM('small', 'medium', 'large'), -- 三选一
status ENUM('draft', 'published', 'archived')
);
-- 插入数据
INSERT INTO products VALUES
(1, 'T-Shirt', 'medium', 'published'),
(2, 'Jacket', 'large', 'draft');
-- 查询
SELECT * FROM products WHERE size = 'medium';
SELECT * FROM products WHERE status IN ('draft', 'published');
SET - 集合类型
sql
-- 创建SET字段
CREATE TABLE users (
id INT,
username VARCHAR(50),
interests SET('reading', 'sports', 'music', 'travel', 'coding')
);
-- 插入数据(可多选)
INSERT INTO users VALUES
(1, '张三', 'reading,music'),
(2, '李四', 'sports,travel,coding'),
(3, '王五', ''); -- 空集合
-- 查询包含特定值的记录
SELECT * FROM users WHERE FIND_IN_SET('music', interests) > 0;
SELECT * FROM users WHERE interests LIKE '%sports%';
7. 实际应用示例
博客系统表设计
sql
CREATE TABLE blog_system (
-- 用户表
users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password CHAR(60), -- bcrypt哈希固定60字符
email VARCHAR(100) NOT NULL,
role ENUM('admin', 'editor', 'author') DEFAULT 'author',
status ENUM('active', 'inactive', 'banned') DEFAULT 'active'
),
-- 文章表
posts (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
slug VARCHAR(200) UNIQUE, -- URL友好标识
content LONGTEXT,
excerpt TEXT,
status ENUM('draft', 'published', 'private') DEFAULT 'draft',
meta_keywords VARCHAR(500), -- 关键词集合
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
),
-- 分类表
categories (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) UNIQUE,
description TINYTEXT
),
-- 标签表(使用SET或关联表)
posts_tags (
post_id INT,
tag_name VARCHAR(50),
PRIMARY KEY(post_id, tag_name)
)
);
8. 选择指南和最佳实践
如何选择合适的类型
sql
-- 1. 固定长度数据 → CHAR
country_code CHAR(2),
postal_code CHAR(6),
user_status CHAR(1),
-- 2. 变长文本数据 → VARCHAR
username VARCHAR(50),
email VARCHAR(100),
title VARCHAR(255),
-- 3. 中等长度文本 → TEXT
content TEXT, -- 文章内容
description TEXT, -- 产品描述
-- 4. 很长文本 → LONGTEXT
book_content LONGTEXT, -- 书籍内容
log_data LONGTEXT, -- 日志数据
-- 5. 预定义选项 → ENUM
status ENUM('active', 'inactive'),
priority ENUM('low', 'medium', 'high'),
-- 6. 多选项 → SET 或 关联表
tags SET('tech', 'science', 'art'), -- 选项少时
-- 或者用关联表(更规范)
性能优化建议
sql
-- 1. VARCHAR长度不要过度分配
-- 不好
title VARCHAR(1000) -- 过度分配
-- 好
title VARCHAR(255) -- 合适长度
-- 2. 为频繁查询的字段创建索引
CREATE INDEX idx_username ON users(username);
CREATE INDEX idx_email ON users(email(100)); -- 前缀索引
-- 3. 大文本字段单独存放(垂直分表)
-- 主表
CREATE TABLE posts (
id INT PRIMARY KEY,
title VARCHAR(255),
excerpt TEXT,
-- 其他元数据
);
-- 内容表
CREATE TABLE post_content (
post_id INT PRIMARY KEY,
content LONGTEXT
);
-- 4. 避免在WHERE条件中使用TEXT/BLOB
-- 不好
SELECT * FROM posts WHERE content LIKE '%keyword%';
-- 好(添加摘要字段)
SELECT * FROM posts WHERE excerpt LIKE '%keyword%';
9. 注意事项
字符集和排序规则
sql
-- 指定字符集
CREATE TABLE multilingual (
content VARCHAR(1000) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
);
-- 查看字符集
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
存储限制
行大小限制:65,535字节(不包括TEXT/BLOB)
VARCHAR最大长度:受行限制和字符集影响
实际可用长度:utf8mb4字符集下,VARCHAR(21845) 是理论最大值
日期和时间类型
1. 日期时间类型概览
MySQL 提供了5种主要的日期时间类型:
类型 格式 范围 存储大小 用途
DATE YYYY-MM-DD 1000-01-01 到 9999-12-31 3字节 存储日期
TIME HH:MM:SS[.fraction] -838:59:59 到 838:59:59 3字节 存储时间
DATETIME YYYY-MM-DD HH:MM:SS[.fraction] 1000-01-01 00:00:00 到 9999-12-31 23:59:59 5-8字节 日期+时间
TIMESTAMP YYYY-MM-DD HH:MM:SS[.fraction] 1970-01-01 00:00:01 到 2038-01-19 03:14:07 4字节 时间戳
YEAR YYYY 1901 到 2155 1字节 存储年份
2. DATE 类型
基本用法
sql
-- 创建表
CREATE TABLE events (
id INT PRIMARY KEY AUTO_INCREMENT,
event_name VARCHAR(100),
event_date DATE, -- 只存储日期
created_at DATE
);
-- 插入数据
INSERT INTO events (event_name, event_date, created_at)
VALUES
('产品发布会', '2024-03-15', CURDATE()),
('技术研讨会', '2024-04-20', '2024-01-10'),
('年度总结会', '2024-12-31', '2024-01-10');
-- 查询
SELECT * FROM events WHERE event_date = '2024-03-15';
SELECT * FROM events WHERE event_date > '2024-03-01';
DATE 函数操作
sql
-- 获取当前日期
SELECT CURDATE(); -- 2024-01-15
SELECT CURRENT_DATE(); -- 2024-01-15
-- 日期计算
SELECT DATE_ADD('2024-01-15', INTERVAL 7 DAY); -- 2024-01-22
SELECT DATE_SUB('2024-01-15', INTERVAL 1 MONTH); -- 2023-12-15
-- 提取日期部分
SELECT YEAR('2024-01-15'); -- 2024
SELECT MONTH('2024-01-15'); -- 1
SELECT DAY('2024-01-15'); -- 15
SELECT DAYNAME('2024-01-15'); -- Monday
-- 日期格式化
SELECT DATE_FORMAT('2024-01-15', '%Y年%m月%d日'); -- 2024年01月15日
3. TIME 类型
基本用法
sql
-- 创建表
CREATE TABLE schedules (
id INT PRIMARY KEY,
task_name VARCHAR(100),
start_time TIME, -- 只存储时间
duration TIME, -- 持续时间
end_time TIME
);
-- 插入数据
INSERT INTO schedules VALUES
(1, '晨会', '09:00:00', '01:00:00', '10:00:00'),
(2, '午休', '12:00:00', '01:30:00', '13:30:00'),
(3, '项目讨论', '14:30:00', '02:15:00', '16:45:00');
-- 查询
SELECT * FROM schedules WHERE start_time BETWEEN '09:00:00' AND '12:00:00';
TIME 函数操作
sql
-- 获取当前时间
SELECT CURTIME(); -- 14:30:25
SELECT CURRENT_TIME(); -- 14:30:25
-- 时间计算
SELECT ADDTIME('14:30:00', '02:15:00'); -- 16:45:00
SELECT SUBTIME('14:30:00', '01:00:00'); -- 13:30:00
-- 提取时间部分
SELECT HOUR('14:30:25'); -- 14
SELECT MINUTE('14:30:25'); -- 30
SELECT SECOND('14:30:25'); -- 25
-- 时间格式化
SELECT TIME_FORMAT('14:30:25', '%h:%i %p'); -- 02:30 PM
4. DATETIME 类型
基本用法
sql
-- 创建表(博客系统示例)
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
content TEXT,
created_at DATETIME, -- 创建时间
updated_at DATETIME, -- 更新时间
published_at DATETIME -- 发布时间
);
-- 插入数据
INSERT INTO articles (title, content, created_at, updated_at, published_at)
VALUES
('MySQL教程', '内容...', NOW(), NOW(), '2024-01-15 10:00:00'),
('PHP基础', '内容...', '2024-01-14 15:30:00', '2024-01-14 16:45:00', '2024-01-14 17:00:00');
-- 查询
SELECT * FROM articles WHERE published_at >= '2024-01-15 00:00:00';
SELECT * FROM articles WHERE created_at BETWEEN '2024-01-14 00:00:00' AND '2024-01-15 23:59:59';
DATETIME 函数操作
sql
-- 获取当前日期时间
SELECT NOW(); -- 2024-01-15 14:30:25
SELECT CURRENT_TIMESTAMP(); -- 2024-01-15 14:30:25
-- 日期时间计算
SELECT DATE_ADD(NOW(), INTERVAL 1 HOUR); -- 增加1小时
SELECT DATE_SUB(NOW(), INTERVAL 30 MINUTE); -- 减少30分钟
-- 提取部分
SELECT DATE(NOW()); -- 2024-01-15(日期部分)
SELECT TIME(NOW()); -- 14:30:25(时间部分)
-- 格式化
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 2024-01-15 14:30:25
SELECT DATE_FORMAT(NOW(), '%W, %M %d, %Y'); -- Monday, January 15, 2024
5. TIMESTAMP 类型
基本用法
sql
-- 创建表(自动时间戳)
CREATE TABLE user_actions (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
action VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 自动设置创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 自动更新
);
-- 插入数据(created_at 会自动填充)
INSERT INTO user_actions (user_id, action)
VALUES
(1, 'login'),
(2, 'view_page'),
(3, 'logout');
-- 更新数据(updated_at 会自动更新)
UPDATE user_actions SET action = 'view_profile' WHERE id = 2;
TIMESTAMP 特性
sql
-- TIMESTAMP 与时区
SET time_zone = '+08:00'; -- 设置为东八区
SELECT @@time_zone; -- 查看当前时区
-- TIMESTAMP 范围限制
INSERT INTO user_actions (user_id, action, created_at)
VALUES (4, 'test', '2038-01-19 03:14:07'); -- 最大支持时间
-- 超出范围会报错
INSERT INTO user_actions (user_id, action, created_at)
VALUES (5, 'test', '2038-01-20 00:00:00'); -- 错误!
6. YEAR 类型
基本用法
sql
-- 创建表
CREATE TABLE vehicles (
id INT PRIMARY KEY,
model VARCHAR(50),
manufacture_year YEAR, -- 4位年份
purchase_year YEAR(4) -- 明确指定4位
);
-- 插入数据
INSERT INTO vehicles VALUES
(1, 'Toyota Camry', 2020, 2021),
(2, 'Honda Civic', 2019, 2020),
(3, 'Ford Focus', 2022, 2023);
-- 查询
SELECT * FROM vehicles WHERE manufacture_year >= 2020;
7. 实际应用示例
博客系统完整设计
sql
CREATE TABLE blog_system (
-- 用户表
users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login DATETIME,
birth_date DATE, -- 生日
membership_expiry DATE -- 会员到期日
),
-- 文章表
articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
content TEXT,
status ENUM('draft', 'published', 'archived'),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
published_at DATETIME, -- 计划发布时间
reading_time TIME -- 预计阅读时间
),
-- 评论表
comments (
id INT PRIMARY KEY AUTO_INCREMENT,
article_id INT,
user_id INT,
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
is_approved BOOLEAN DEFAULT FALSE
),
-- 系统日志表
system_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
log_level ENUM('info', 'warning', 'error'),
message TEXT,
log_time DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), -- 微秒精度
source VARCHAR(100)
)
);
8. 日期时间函数详解
常用函数示例
sql
-- 1. 当前时间相关
SELECT NOW(), CURDATE(), CURTIME(), UNIX_TIMESTAMP();
-- 2. 日期时间提取
SELECT
YEAR(NOW()) as year,
MONTH(NOW()) as month,
DAY(NOW()) as day,
HOUR(NOW()) as hour,
MINUTE(NOW()) as minute,
SECOND(NOW()) as second;
-- 3. 日期时间计算
SELECT
DATE_ADD(NOW(), INTERVAL 1 DAY) as tomorrow,
DATE_SUB(NOW(), INTERVAL 1 WEEK) as last_week,
DATE_ADD(NOW(), INTERVAL 3 MONTH) as in_3_months;
-- 4. 日期差计算
SELECT
DATEDIFF('2024-01-20', '2024-01-15') as day_diff, -- 5
TIMEDIFF('14:30:00', '12:00:00') as time_diff; -- 02:30:00
-- 5. 日期格式化
SELECT
DATE_FORMAT(NOW(), '%Y-%m-%d') as simple_date,
DATE_FORMAT(NOW(), '%W, %M %e, %Y') as full_date,
DATE_FORMAT(NOW(), '%h:%i %p') as am_pm_time;
时间间隔类型
sql
-- INTERVAL 支持的单位
SELECT
NOW() + INTERVAL 1 MICROSECOND,
NOW() + INTERVAL 1 SECOND,
NOW() + INTERVAL 1 MINUTE,
NOW() + INTERVAL 1 HOUR,
NOW() + INTERVAL 1 DAY,
NOW() + INTERVAL 1 WEEK,
NOW() + INTERVAL 1 MONTH,
NOW() + INTERVAL 1 QUARTER,
NOW() + INTERVAL 1 YEAR;
9. 选择指南和最佳实践
如何选择合适的类型
sql
-- 1. 只需要日期 → DATE
birth_date DATE,
event_date DATE,
-- 2. 只需要时间 → TIME
start_time TIME,
duration TIME,
-- 3. 完整的日期时间(大范围) → DATETIME
created_at DATETIME,
published_at DATETIME,
-- 4. 自动时间戳、需要时区转换 → TIMESTAMP
last_modified TIMESTAMP,
login_time TIMESTAMP,
-- 5. 只需要年份 → YEAR
manufacture_year YEAR,
graduation_year YEAR
DATETIME vs TIMESTAMP 对比
特性 DATETIME TIMESTAMP
范围 1000-9999年 1970-2038年
时区 不受时区影响 自动时区转换
存储 5-8字节 4字节
默认值 不支持函数默认值 支持CURRENT_TIMESTAMP
自动更新 不支持 支持ON UPDATE
适用场景 生日、历史日期 创建时间、修改时间
性能优化建议
sql
-- 1. 为日期时间字段创建索引
CREATE INDEX idx_created_at ON articles(created_at);
CREATE INDEX idx_published_date ON articles(DATE(published_at));
-- 2. 避免在WHERE条件中使用函数(使用范围查询)
-- 不好
SELECT * FROM articles WHERE YEAR(created_at) = 2024;
-- 好
SELECT * FROM articles WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
-- 3. 使用合适的精度
-- 不需要微秒精度
created_at DATETIME, -- 秒级精度
-- 需要高精度
log_time DATETIME(6), -- 微秒精度
-- 4. 分区表按时间分区
CREATE TABLE logs (
id INT,
log_time DATETIME,
message TEXT
) PARTITION BY RANGE (YEAR(log_time)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);
10. 高级用法
时区处理
sql
-- 设置时区
SET time_zone = '+08:00'; -- 东八区(北京时间)
SET time_zone = 'Asia/Shanghai';
-- 转换时区
SELECT
NOW() as local_time,
CONVERT_TZ(NOW(), 'SYSTEM', 'UTC') as utc_time,
CONVERT_TZ(NOW(), 'SYSTEM', 'America/New_York') as ny_time;
微秒精度
sql
-- 创建支持微秒的表
CREATE TABLE high_precision_logs (
id INT PRIMARY KEY,
event_time DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), -- 6位小数
description TEXT
);
-- 插入数据
INSERT INTO high_precision_logs (description) VALUES ('精确时间记录');
生成日期序列
sql
-- 生成最近7天的日期
SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as date
FROM
(SELECT 0 as a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as a
CROSS JOIN
(SELECT 0 as a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as b
CROSS JOIN
(SELECT 0 as a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) as c
WHERE (a.a + (10 * b.a) + (100 * c.a)) <= 6
ORDER BY date DESC;