Skip to content

数据类型

MySQL支持多种数据类型,用于定义表中列可以存储的数据类型。本章将详细介绍MySQL的各种数据类型及其使用方法。

数值类型

整数类型

sql
/*
 * MySQL整数类型:
 * 
 * 类型         字节    有符号范围                  无符号范围
 * 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      很大                        很大
 */

-- 创建表演示整数类型
CREATE TABLE int_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    age TINYINT UNSIGNED,          -- 年龄(0-255)
    quantity SMALLINT,             -- 数量
    population INT,                -- 人口
    big_number BIGINT              -- 大数字
);

-- 插入数据
INSERT INTO int_types (age, quantity, population, big_number)
VALUES (25, 1000, 1400000000, 9000000000000000000);

-- 查询数据
SELECT * FROM int_types;

-- 显示宽度(不影响存储范围,只影响显示)
CREATE TABLE display_width (
    num INT(5) ZEROFILL   -- 不足5位用0填充
);

INSERT INTO display_width VALUES (123);
SELECT * FROM display_width;  -- 显示: 00123

浮点类型

sql
/*
 * MySQL浮点类型:
 * 
 * 类型         字节    说明
 * FLOAT        4      单精度浮点数
 * DOUBLE       8      双精度浮点数
 * DECIMAL      可变   精确小数
 */

-- 创建表演示浮点类型
CREATE TABLE float_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    price FLOAT,                   -- 单精度
    score DOUBLE,                  -- 双精度
    amount DECIMAL(10, 2)          -- 精确小数(10位,2位小数)
);

-- 插入数据
INSERT INTO float_types (price, score, amount)
VALUES (19.99, 95.5678, 12345.67);

-- 查询数据
SELECT * FROM float_types;

-- 浮点精度问题演示
CREATE TABLE precision_test (
    f_float FLOAT,
    f_double DOUBLE,
    f_decimal DECIMAL(20, 10)
);

INSERT INTO precision_test 
VALUES (0.1 + 0.2, 0.1 + 0.2, 0.1 + 0.2);

SELECT * FROM precision_test;
/*
 * 输出:
 * f_float: 0.3(可能有精度误差)
 * f_double: 0.3(更精确但仍有误差)
 * f_decimal: 0.3000000000(精确)
 */

-- DECIMAL用于精确计算(如金额)
CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    price DECIMAL(10, 2)    -- 金额用DECIMAL
);

字符串类型

CHAR和VARCHAR

sql
/*
 * CHAR和VARCHAR的区别:
 * 
 * CHAR(n):固定长度,不足补空格,最大255
 * VARCHAR(n):可变长度,按实际存储,最大65535
 */

-- 创建表演示字符串类型
CREATE TABLE string_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code CHAR(10),              -- 固定长度(如编码)
    name VARCHAR(50),           -- 可变长度
    description VARCHAR(1000)   -- 长文本
);

-- 插入数据
INSERT INTO string_types (code, name, description)
VALUES ('ABC123', '商品A', '这是一个商品描述');

-- CHAR会自动补空格
INSERT INTO string_types (code, name, description)
VALUES ('XY', '商品B', '短编码');

-- 查看存储长度
SELECT 
    code,
    CHAR_LENGTH(code) AS len,
    name,
    CHAR_LENGTH(name) AS name_len
FROM string_types;

/*
 * 使用建议:
 * - 固定长度用CHAR(如手机号、身份证号)
 * - 可变长度用VARCHAR(如姓名、地址)
 */

TEXT类型

sql
/*
 * TEXT类型(用于存储大文本):
 * 
 * 类型         最大长度
 * TINYTEXT     255字节
 * TEXT         65535字节(64KB)
 * MEDIUMTEXT   16MB
 * LONGTEXT     4GB
 */

-- 创建表演示TEXT类型
CREATE TABLE text_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    content TEXT,               -- 文章内容
    article MEDIUMTEXT          -- 长文章
);

-- 插入数据
INSERT INTO text_types (title, content, article)
VALUES (
    '文章标题',
    '这是一段文章内容...',
    REPEAT('很长的文章内容...', 1000)
);

-- 查询数据
SELECT id, title, CHAR_LENGTH(content) AS content_len
FROM text_types;

BLOB类型

sql
/*
 * BLOB类型(用于存储二进制数据):
 * 
 * 类型         最大长度
 * TINYBLOB     255字节
 * BLOB         65535字节(64KB)
 * MEDIUMBLOB   16MB
 * LONGBLOB     4GB
 */

-- 创建表演示BLOB类型
CREATE TABLE blob_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    file_name VARCHAR(100),
    file_data MEDIUMBLOB,       -- 文件数据
    file_size INT               -- 文件大小
);

-- 注意:大文件建议存储路径,而非直接存储二进制数据
-- 更好的设计:
CREATE TABLE files (
    id INT PRIMARY KEY AUTO_INCREMENT,
    file_name VARCHAR(100),
    file_path VARCHAR(255),     -- 文件路径
    file_size INT,
    file_type VARCHAR(50)
);

ENUM和SET

sql
/*
 * ENUM:枚举类型,只能选一个值
 * SET:集合类型,可以选择多个值
 */

-- 创建表演示ENUM和SET
CREATE TABLE enum_set_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('active', 'inactive', 'pending'),  -- 状态
    gender ENUM('男', '女', '未知'),                -- 性别
    hobbies SET('阅读', '运动', '音乐', '旅行')      -- 爱好(可多选)
);

-- 插入数据
INSERT INTO enum_set_types (status, gender, hobbies)
VALUES ('active', '男', '阅读,运动');

INSERT INTO enum_set_types (status, gender, hobbies)
VALUES ('pending', '女', '音乐,旅行');

-- 查询数据
SELECT * FROM enum_set_types;

-- 使用数字索引(不推荐)
INSERT INTO enum_set_types (status, gender, hobbies)
VALUES (1, 1, 3);  -- 1='active', 1='男', 3='阅读,运动'

-- 查询特定状态
SELECT * FROM enum_set_types WHERE status = 'active';

-- 查询包含特定爱好的记录
SELECT * FROM enum_set_types 
WHERE FIND_IN_SET('阅读', hobbies) > 0;

日期时间类型

sql
/*
 * MySQL日期时间类型:
 * 
 * 类型         格式                  范围
 * DATE         YYYY-MM-DD           1000-01-01 ~ 9999-12-31
 * TIME         HH:MM:SS             -838:59:59 ~ 838:59:59
 * DATETIME     YYYY-MM-DD HH:MM:SS  1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
 * TIMESTAMP    YYYY-MM-DD HH:MM:SS  1970-01-01 00:00:01 ~ 2038-01-19 03:14:07
 * YEAR         YYYY                 1901 ~ 2155
 */

-- 创建表演示日期时间类型
CREATE TABLE date_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    birth_date DATE,                    -- 出生日期
    work_time TIME,                     -- 工作时间
    create_time DATETIME,               -- 创建时间
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    year_value YEAR                     -- 年份
);

-- 插入数据
INSERT INTO date_types (birth_date, work_time, create_time, year_value)
VALUES ('1990-05-15', '09:00:00', '2024-01-01 10:30:00', 2024);

-- 使用函数插入当前时间
INSERT INTO date_types (birth_date, work_time, create_time, year_value)
VALUES (CURDATE(), CURTIME(), NOW(), YEAR(NOW()));

-- 查询数据
SELECT * FROM date_types;

-- TIMESTAMP自动更新演示
UPDATE date_types SET birth_date = '1991-06-20' WHERE id = 1;
SELECT id, update_time FROM date_types WHERE id = 1;

日期时间函数

sql
-- 获取当前日期时间
SELECT NOW();           -- 2024-01-15 10:30:00
SELECT CURDATE();       -- 2024-01-15
SELECT CURTIME();       -- 10:30:00
SELECT SYSDATE();       -- 执行时的时间

-- 日期时间提取
SELECT YEAR(NOW());     -- 2024
SELECT MONTH(NOW());    -- 1
SELECT DAY(NOW());      -- 15
SELECT HOUR(NOW());     -- 10
SELECT MINUTE(NOW());   -- 30
SELECT SECOND(NOW());   -- 0

-- 日期格式化
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日 %H:%i:%s');
-- 输出: 2024年01月15日 10:30:00

-- 日期计算
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 UNIX_TIMESTAMP();                    -- 当前时间戳
SELECT FROM_UNIXTIME(1705305000);           -- 时间戳转日期

-- 创建带时间戳的表
CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

JSON类型

sql
/*
 * MySQL 5.7+支持JSON类型
 * JSON类型可以存储和查询JSON格式数据
 */

-- 创建表演示JSON类型
CREATE TABLE json_types (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_info JSON,              -- 用户信息
    settings JSON                -- 设置
);

-- 插入JSON数据
INSERT INTO json_types (user_info, settings)
VALUES (
    '{"name": "张三", "age": 25, "city": "北京"}',
    '{"theme": "dark", "language": "zh-CN", "notifications": true}'
);

-- 查询JSON数据
SELECT * FROM json_types;

-- 提取JSON值
SELECT 
    id,
    JSON_EXTRACT(user_info, '$.name') AS name,
    JSON_EXTRACT(user_info, '$.age') AS age,
    user_info->>'$.city' AS city     -- 简写方式
FROM json_types;

-- 修改JSON数据
UPDATE json_types 
SET user_info = JSON_SET(user_info, '$.age', 26)
WHERE id = 1;

-- 添加JSON属性
UPDATE json_types 
SET user_info = JSON_SET(user_info, '$.email', 'zhangsan@example.com')
WHERE id = 1;

-- 删除JSON属性
UPDATE json_types 
SET user_info = JSON_REMOVE(user_info, '$.email')
WHERE id = 1;

-- JSON数组操作
INSERT INTO json_types (user_info, settings)
VALUES (
    '{"name": "李四", "hobbies": ["阅读", "运动", "音乐"]}',
    '{}'
);

-- 查询JSON数组
SELECT user_info->>'$.hobbies[0]' AS first_hobby
FROM json_types WHERE id = 2;

-- JSON搜索
SELECT * FROM json_types 
WHERE JSON_CONTAINS(user_info, '"张三"', '$.name');

数据类型选择建议

sql
/*
 * 数据类型选择建议:
 * 
 * 1. 整数类型
 *    - 小范围整数:TINYINT(年龄、状态)
 *    - 普通整数:INT(ID、数量)
 *    - 大整数:BIGINT(订单号、金额分)
 * 
 * 2. 小数类型
 *    - 精确计算:DECIMAL(金额、价格)
 *    - 科学计算:DOUBLE
 * 
 * 3. 字符串类型
 *    - 固定长度:CHAR(手机号、编码)
 *    - 可变长度:VARCHAR(姓名、地址)
 *    - 长文本:TEXT(文章内容)
 * 
 * 4. 日期时间类型
 *    - 日期:DATE(生日)
 *    - 时间:TIME(营业时间)
 *    - 日期时间:DATETIME(创建时间)
 *    - 自动更新:TIMESTAMP
 * 
 * 5. 特殊类型
 *    - 单选:ENUM(状态、性别)
 *    - 多选:SET(标签、爱好)
 *    - JSON数据:JSON(配置、扩展信息)
 */

-- 综合示例:用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    password CHAR(64) NOT NULL,           -- SHA256哈希
    email VARCHAR(100),
    phone CHAR(11),                        -- 手机号
    age TINYINT UNSIGNED,                  -- 年龄
    gender ENUM('男', '女', '未知') DEFAULT '未知',
    balance DECIMAL(10, 2) DEFAULT 0.00,   -- 余额
    avatar VARCHAR(255),                   -- 头像URL
    status TINYINT DEFAULT 1,              -- 状态:1正常 0禁用
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

本章小结

本章学习了:

  • 数值类型:INT、BIGINT、DECIMAL、FLOAT、DOUBLE
  • 字符串类型:CHAR、VARCHAR、TEXT、BLOB
  • 枚举集合:ENUM、SET
  • 日期时间:DATE、TIME、DATETIME、TIMESTAMP
  • JSON类型:JSON数据存储和查询
  • 类型选择:根据业务需求选择合适的数据类型

下一章,我们将学习表操作,了解如何创建和管理数据表。