TiDB数据类型 #
一、数据类型概览 #
1.1 类型分类 #
text
TiDB 数据类型
├── 数值类型
│ ├── 整数类型
│ │ ├── TINYINT
│ │ ├── SMALLINT
│ │ ├── MEDIUMINT
│ │ ├── INT / INTEGER
│ │ └── BIGINT
│ ├── 浮点类型
│ │ ├── FLOAT
│ │ └── DOUBLE
│ └── 定点类型
│ └── DECIMAL
│
├── 字符串类型
│ ├── CHAR
│ ├── VARCHAR
│ ├── TEXT
│ │ ├── TINYTEXT
│ │ ├── TEXT
│ │ ├── MEDIUMTEXT
│ │ └── LONGTEXT
│ └── BLOB
│ ├── TINYBLOB
│ ├── BLOB
│ ├── MEDIUMBLOB
│ └── LONGBLOB
│
├── 日期时间类型
│ ├── DATE
│ ├── TIME
│ ├── DATETIME
│ ├── TIMESTAMP
│ └── YEAR
│
├── JSON类型
│ └── JSON
│
└── 其他类型
├── BOOLEAN / BOOL
├── ENUM
├── SET
└── BIT
1.2 MySQL兼容性 #
TiDB 高度兼容 MySQL 数据类型,大多数情况下可以直接迁移。
| 兼容级别 | 说明 |
|---|---|
| 完全兼容 | 数值、字符串、日期时间类型 |
| 高度兼容 | JSON、ENUM、SET 类型 |
| 部分兼容 | 某些精度和边界值处理 |
二、数值类型 #
2.1 整数类型 #
类型范围
| 类型 | 字节 | 有符号范围 | 无符号范围 |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2 | -32768 ~ 32767 | 0 ~ 65535 |
| MEDIUMINT | 3 | -8388608 ~ 8388607 | 0 ~ 16777215 |
| INT | 4 | -2^31 ~ 2^31-1 | 0 ~ 2^32-1 |
| BIGINT | 8 | -2^63 ~ 2^63-1 | 0 ~ 2^64-1 |
使用示例
sql
-- 创建表
CREATE TABLE integers (
id INT AUTO_INCREMENT PRIMARY KEY,
tiny_col TINYINT,
tiny_unsigned TINYINT UNSIGNED,
small_col SMALLINT,
medium_col MEDIUMINT,
int_col INT,
int_unsigned INT UNSIGNED,
big_col BIGINT
);
-- 插入数据
INSERT INTO integers (tiny_col, tiny_unsigned, small_col, medium_col, int_col, int_unsigned, big_col)
VALUES
(127, 255, 32767, 8388607, 2147483647, 4294967295, 9223372036854775807);
-- 查询
SELECT * FROM integers;
显示宽度
sql
-- 显示宽度不影响存储范围
-- INT(11) 和 INT 存储范围相同
CREATE TABLE display_width (
id INT(11) ZEROFILL,
age INT(3) ZEROFILL
);
INSERT INTO display_width VALUES (1, 5);
-- 查询结果: id = 00000000001, age = 005
SELECT * FROM display_width;
2.2 浮点类型 #
类型说明
| 类型 | 字节 | 精度 |
|---|---|---|
| FLOAT | 4 | 单精度,约7位有效数字 |
| DOUBLE | 8 | 双精度,约15位有效数字 |
使用示例
sql
CREATE TABLE floats (
id INT AUTO_INCREMENT PRIMARY KEY,
float_col FLOAT,
float_precision FLOAT(10, 2),
double_col DOUBLE,
double_precision DOUBLE(20, 8)
);
INSERT INTO floats (float_col, float_precision, double_col, double_precision)
VALUES
(3.14159, 12345.67, 3.14159265358979, 1234567890.12345678);
SELECT * FROM floats;
注意事项
sql
-- 浮点数精度问题
SELECT 0.1 + 0.2;
-- 结果可能不是精确的 0.3
-- 金融计算建议使用 DECIMAL
SELECT CAST(0.1 AS DECIMAL(10, 2)) + CAST(0.2 AS DECIMAL(10, 2));
-- 结果: 0.30
2.3 定点类型 #
DECIMAL 类型
sql
-- DECIMAL(M, D)
-- M: 总位数 (精度)
-- D: 小数位数 (标度)
CREATE TABLE decimals (
id INT AUTO_INCREMENT PRIMARY KEY,
price DECIMAL(10, 2),
rate DECIMAL(5, 4),
amount DECIMAL(20, 6)
);
INSERT INTO decimals (price, rate, amount)
VALUES
(99999999.99, 1.2345, 12345678901234.567890);
SELECT * FROM decimals;
金融场景示例
sql
-- 账户余额表
CREATE TABLE accounts (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
balance DECIMAL(20, 2) NOT NULL DEFAULT 0.00,
frozen_amount DECIMAL(20, 2) NOT NULL DEFAULT 0.00,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 转账事务
BEGIN;
UPDATE accounts SET balance = balance - 100.00 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100.00 WHERE user_id = 2;
COMMIT;
-- 查询余额
SELECT user_id, balance FROM accounts;
三、字符串类型 #
3.1 CHAR 和 VARCHAR #
类型对比
| 类型 | 说明 | 最大长度 |
|---|---|---|
| CHAR(M) | 定长字符串 | 255 字符 |
| VARCHAR(M) | 变长字符串 | 65535 字节 |
使用示例
sql
CREATE TABLE strings (
id INT AUTO_INCREMENT PRIMARY KEY,
char_col CHAR(10),
varchar_col VARCHAR(255),
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE
);
INSERT INTO strings (char_col, varchar_col, name, email)
VALUES
('hello', 'This is a variable length string', 'Alice', 'alice@example.com'),
('world', 'Another string', 'Bob', 'bob@example.com');
SELECT * FROM strings;
存储差异
sql
-- CHAR 定长存储,不足补空格
-- CHAR(10) 存储 'hello' 实际存储 'hello '
-- VARCHAR 变长存储,按实际长度
-- VARCHAR(10) 存储 'hello' 实际存储 'hello' (5字节 + 长度前缀)
-- 查询时 CHAR 会去掉尾部空格
SELECT char_col, LENGTH(char_col), CHAR_LENGTH(char_col) FROM strings;
3.2 TEXT 类型 #
类型范围
| 类型 | 最大长度 |
|---|---|
| TINYTEXT | 255 字节 |
| TEXT | 65535 字节 |
| MEDIUMTEXT | 16MB |
| LONGTEXT | 4GB |
使用示例
sql
CREATE TABLE articles (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
summary TEXT,
content MEDIUMTEXT,
attachments LONGTEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO articles (title, summary, content)
VALUES
('TiDB入门教程', '这是一篇TiDB入门教程', '详细内容...'),
('分布式数据库设计', '分布式数据库设计原理', '详细内容...');
SELECT id, title, summary FROM articles;
TEXT vs VARCHAR
sql
-- VARCHAR 适合较短的字符串
-- TEXT 适合大文本
-- VARCHAR 可以有默认值
CREATE TABLE test1 (
name VARCHAR(100) DEFAULT 'unknown'
);
-- TEXT 不能有默认值
CREATE TABLE test2 (
content TEXT DEFAULT NULL
);
3.3 BLOB 类型 #
类型范围
| 类型 | 最大长度 |
|---|---|
| TINYBLOB | 255 字节 |
| BLOB | 65535 字节 |
| MEDIUMBLOB | 16MB |
| LONGBLOB | 4GB |
使用示例
sql
CREATE TABLE files (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
filename VARCHAR(255) NOT NULL,
mime_type VARCHAR(100),
file_size INT,
file_data LONGBLOB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入二进制数据 (通常通过应用程序)
-- INSERT INTO files (filename, mime_type, file_size, file_data)
-- VALUES ('image.png', 'image/png', 1024, ?);
3.4 字符集和排序规则 #
sql
-- 查看支持的字符集
SHOW CHARACTER SET;
-- 查看排序规则
SHOW COLLATION;
-- 指定字符集
CREATE TABLE charset_test (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
) DEFAULT CHARSET=utf8mb4;
-- 常用字符集
-- utf8mb4: 完整 UTF-8,支持 emoji
-- utf8: MySQL 的 utf8 是 utf8mb3,不支持 emoji
-- latin1: 西欧字符集
-- 常用排序规则
-- utf8mb4_general_ci: 快速,但不精确
-- utf8mb4_unicode_ci: 精确,推荐使用
-- utf8mb4_bin: 二进制比较,区分大小写
四、日期时间类型 #
4.1 类型概览 #
| 类型 | 格式 | 范围 |
|---|---|---|
| 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 |
4.2 DATE 类型 #
sql
CREATE TABLE dates (
id INT AUTO_INCREMENT PRIMARY KEY,
birth_date DATE NOT NULL,
hire_date DATE,
event_date DATE
);
INSERT INTO dates (birth_date, hire_date, event_date)
VALUES
('1990-05-15', '2020-01-01', '2024-12-25'),
('1985-08-20', '2018-06-15', '2024-01-01');
-- 日期函数
SELECT
birth_date,
YEAR(birth_date) AS year,
MONTH(birth_date) AS month,
DAY(birth_date) AS day,
DAYOFWEEK(birth_date) AS weekday,
DAYNAME(birth_date) AS weekday_name
FROM dates;
4.3 TIME 类型 #
sql
CREATE TABLE times (
id INT AUTO_INCREMENT PRIMARY KEY,
start_time TIME,
end_time TIME,
duration TIME
);
INSERT INTO times (start_time, end_time, duration)
VALUES
('09:00:00', '18:00:00', '09:00:00'),
('08:30:00', '17:30:00', '09:00:00');
-- 时间函数
SELECT
start_time,
end_time,
TIMEDIFF(end_time, start_time) AS diff,
HOUR(start_time) AS hour,
MINUTE(start_time) AS minute
FROM times;
4.4 DATETIME 类型 #
sql
CREATE TABLE events (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(100) NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO events (event_name, start_time, end_time)
VALUES
('会议', '2024-03-27 10:00:00', '2024-03-27 12:00:00'),
('培训', '2024-03-28 14:00:00', '2024-03-28 17:00:00');
-- 日期时间函数
SELECT
event_name,
start_time,
DATE_FORMAT(start_time, '%Y年%m月%d日 %H:%i') AS formatted,
TIMESTAMPDIFF(HOUR, start_time, end_time) AS hours
FROM events;
4.5 TIMESTAMP 类型 #
sql
CREATE TABLE timestamps (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO timestamps (name) VALUES ('test1');
-- 等待一秒
-- UPDATE timestamps SET name = 'test1_updated' WHERE id = 1;
SELECT * FROM timestamps;
-- TIMESTAMP 特点
-- 1. 自动更新
-- 2. 时区转换
-- 3. 范围限制到 2038 年
DATETIME vs TIMESTAMP
sql
-- 区别对比
CREATE TABLE datetime_vs_timestamp (
id INT AUTO_INCREMENT PRIMARY KEY,
dt_col DATETIME,
ts_col TIMESTAMP
);
INSERT INTO datetime_vs_timestamp (dt_col, ts_col)
VALUES (NOW(), NOW());
SELECT
dt_col,
ts_col,
FROM_UNIXTIME(UNIX_TIMESTAMP(dt_col)) AS dt_to_unix
FROM datetime_vs_timestamp;
-- 主要区别:
-- 1. 范围: DATETIME 更大
-- 2. 时区: TIMESTAMP 受时区影响
-- 3. 存储: TIMESTAMP 4字节, DATETIME 8字节
-- 4. 默认值: TIMESTAMP 可自动更新
4.6 YEAR 类型 #
sql
CREATE TABLE years (
id INT AUTO_INCREMENT PRIMARY KEY,
year_col YEAR,
description VARCHAR(100)
);
INSERT INTO years (year_col, description)
VALUES
(2024, '今年'),
(2025, '明年'),
(1999, '上世纪');
SELECT * FROM years;
五、JSON类型 #
5.1 基本使用 #
sql
CREATE TABLE json_data (
id INT AUTO_INCREMENT PRIMARY KEY,
data JSON,
config JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入 JSON 数据
INSERT INTO json_data (data, config)
VALUES
('{"name": "Alice", "age": 25, "skills": ["MySQL", "TiDB"]}',
'{"theme": "dark", "language": "zh-CN"}'),
('{"name": "Bob", "age": 30, "address": {"city": "Beijing", "zip": "100000"}}',
'{"theme": "light", "language": "en-US"}');
SELECT * FROM json_data;
5.2 JSON函数 #
提取数据
sql
-- 提取 JSON 值
SELECT
id,
JSON_EXTRACT(data, '$.name') AS name,
JSON_EXTRACT(data, '$.age') AS age,
data->>'$.name' AS name_text,
data->'$.skills' AS skills
FROM json_data;
-- 提取嵌套数据
SELECT
id,
data->>'$.address.city' AS city,
data->>'$.address.zip' AS zip
FROM json_data
WHERE data->>'$.address.city' IS NOT NULL;
-- 提取数组元素
SELECT
id,
data->'$.skills[0]' AS first_skill,
JSON_LENGTH(data, '$.skills') AS skills_count
FROM json_data
WHERE JSON_TYPE(data->'$.skills') = 'ARRAY';
修改数据
sql
-- 设置 JSON 值
UPDATE json_data
SET data = JSON_SET(data, '$.age', 26)
WHERE id = 1;
-- 添加新字段
UPDATE json_data
SET data = JSON_SET(data, '$.email', 'alice@example.com')
WHERE id = 1;
-- 删除字段
UPDATE json_data
SET data = JSON_REMOVE(data, '$.email')
WHERE id = 1;
-- 追加数组元素
UPDATE json_data
SET data = JSON_ARRAY_APPEND(data, '$.skills', 'PostgreSQL')
WHERE id = 1;
查询条件
sql
-- JSON 包含
SELECT * FROM json_data
WHERE JSON_CONTAINS(data, '"Alice"', '$.name');
-- JSON 路径存在
SELECT * FROM json_data
WHERE JSON_CONTAINS_PATH(data, 'one', '$.address');
-- JSON 搜索
SELECT * FROM json_data
WHERE JSON_SEARCH(data, 'one', 'Beijing') IS NOT NULL;
5.3 JSON索引 #
sql
-- TiDB 支持对 JSON 字段创建虚拟列索引
CREATE TABLE json_index (
id INT AUTO_INCREMENT PRIMARY KEY,
data JSON,
name VARCHAR(100) AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.name'))) VIRTUAL,
INDEX idx_name (name)
);
INSERT INTO json_index (data)
VALUES
('{"name": "Alice", "age": 25}'),
('{"name": "Bob", "age": 30}');
-- 使用索引查询
SELECT * FROM json_index WHERE name = 'Alice';
六、其他类型 #
6.1 BOOLEAN类型 #
sql
-- BOOLEAN 是 TINYINT(1) 的别名
CREATE TABLE booleans (
id INT AUTO_INCREMENT PRIMARY KEY,
is_active BOOLEAN DEFAULT TRUE,
is_deleted BOOLEAN DEFAULT FALSE
);
INSERT INTO booleans (is_active, is_deleted)
VALUES (TRUE, FALSE), (FALSE, TRUE), (1, 0);
SELECT
id,
is_active,
is_deleted,
is_active IS TRUE AS active_check
FROM booleans;
6.2 ENUM类型 #
sql
CREATE TABLE enums (
id INT AUTO_INCREMENT PRIMARY KEY,
status ENUM('pending', 'active', 'inactive', 'deleted') DEFAULT 'pending',
priority ENUM('low', 'medium', 'high') NOT NULL
);
INSERT INTO enums (status, priority)
VALUES
('active', 'high'),
('inactive', 'low'),
('pending', 'medium');
-- 查询
SELECT
id,
status,
priority,
status + 0 AS status_index
FROM enums;
-- 严格模式
SET sql_mode = 'strict_trans_tables';
INSERT INTO enums (status, priority) VALUES ('invalid', 'high');
6.3 SET类型 #
sql
CREATE TABLE sets (
id INT AUTO_INCREMENT PRIMARY KEY,
permissions SET('read', 'write', 'delete', 'admin')
);
INSERT INTO sets (permissions)
VALUES
('read,write'),
('read,write,delete'),
('admin');
-- 查询
SELECT
id,
permissions,
FIND_IN_SET('write', permissions) AS has_write
FROM sets;
-- 包含特定权限
SELECT * FROM sets
WHERE FIND_IN_SET('write', permissions) > 0;
6.4 BIT类型 #
sql
CREATE TABLE bits (
id INT AUTO_INCREMENT PRIMARY KEY,
flags BIT(8),
options BIT(16)
);
INSERT INTO bits (flags, options)
VALUES (b'00001010', b'1111000011110000');
-- 查询
SELECT
id,
flags,
flags + 0 AS flags_decimal,
BIN(flags + 0) AS flags_binary
FROM bits;
-- 位操作
SELECT
flags,
flags & b'00000010' AS bit_1_check,
flags | b'00010000' AS set_bit_4
FROM bits;
七、类型选择建议 #
7.1 数值类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 主键ID | BIGINT AUTO_INCREMENT |
| 年龄 | TINYINT UNSIGNED |
| 数量 | INT |
| 金额 | DECIMAL(20, 2) |
| 百分比 | DECIMAL(5, 2) |
| 科学计算 | DOUBLE |
7.2 字符串类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 用户名 | VARCHAR(50) |
| 邮箱 | VARCHAR(255) |
| 手机号 | VARCHAR(20) |
| 文章标题 | VARCHAR(200) |
| 文章内容 | MEDIUMTEXT |
| 文件数据 | LONGBLOB |
7.3 日期时间选择 #
| 场景 | 推荐类型 |
|---|---|
| 出生日期 | DATE |
| 创建时间 | TIMESTAMP |
| 更新时间 | TIMESTAMP |
| 事件时间 | DATETIME |
| 日志时间 | TIMESTAMP |
7.4 特殊类型选择 #
| 场景 | 推荐类型 |
|---|---|
| 开关状态 | BOOLEAN |
| 固定选项 | ENUM |
| 多选组合 | SET |
| 配置数据 | JSON |
| 标志位 | BIT |
八、类型转换 #
8.1 显式转换 #
sql
-- CAST 函数
SELECT
CAST('123' AS SIGNED) AS int_val,
CAST('123.45' AS DECIMAL(10, 2)) AS decimal_val,
CAST(123 AS CHAR) AS char_val,
CAST('2024-03-27' AS DATE) AS date_val;
-- CONVERT 函数
SELECT
CONVERT('123', SIGNED) AS int_val,
CONVERT('abc' USING utf8mb4) AS utf8_val;
8.2 隐式转换 #
sql
-- 数值与字符串转换
SELECT '123' + 456;
SELECT CONCAT(123, 'abc');
-- 日期转换
SELECT DATE('2024-03-27 10:30:00');
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d');
九、总结 #
TiDB 数据类型最佳实践:
| 建议 | 说明 |
|---|---|
| 选择合适类型 | 避免过大或过小 |
| 使用 UNSIGNED | 正数场景扩大范围 |
| 金额用 DECIMAL | 避免精度丢失 |
| 时间用 TIMESTAMP | 自动更新、时区支持 |
| 文本用 utf8mb4 | 支持完整 Unicode |
| JSON 存储灵活数据 | 配置、扩展字段 |
下一步,让我们深入学习 TiDB 的核心组件!
最后更新:2026-03-27