MariaDB数据类型 #

一、数据类型概述 #

1.1 类型分类 #

text
MariaDB数据类型
├── 数值类型
│   ├── 整数类型
│   │   ├── TINYINT
│   │   ├── SMALLINT
│   │   ├── MEDIUMINT
│   │   ├── INT
│   │   └── BIGINT
│   ├── 浮点类型
│   │   ├── FLOAT
│   │   └── DOUBLE
│   └── 定点类型
│       └── DECIMAL
├── 字符串类型
│   ├── CHAR
│   ├── VARCHAR
│   ├── TEXT系列
│   └── BLOB系列
├── 日期时间类型
│   ├── DATE
│   ├── TIME
│   ├── DATETIME
│   ├── TIMESTAMP
│   └── YEAR
├── JSON类型
│   └── JSON
├── 空间类型
│   ├── GEOMETRY
│   ├── POINT
│   ├── LINESTRING
│   └── POLYGON
└── 其他类型
    ├── 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
);

INSERT INTO integers VALUES (127, 32767, 8388607, 2147483647, 9223372036854775807);

-- 无符号整数
CREATE TABLE unsigned_integers (
    tiny_unsigned TINYINT UNSIGNED,
    int_unsigned INT UNSIGNED
);

INSERT INTO unsigned_integers VALUES (255, 4294967295);

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

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

2.3 MariaDB特有整数类型 #

sql
-- MariaDB 10.5+ 支持 BOOLEAN 类型别名
CREATE TABLE bool_example (
    is_active BOOLEAN  -- 等同于 TINYINT(1)
);

-- 序列类型(MariaDB 10.3+)
CREATE TABLE sequence_example (
    id INT AUTO_INCREMENT PRIMARY KEY
);

-- 使用序列引擎
CREATE TABLE seq ENGINE=SEQUENCE;
SELECT * FROM seq WHERE seq=1 FOR UPDATE;

2.4 选择建议 #

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

三、浮点类型 #

3.1 浮点类型列表 #

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

3.2 浮点类型使用 #

sql
CREATE TABLE float_table (
    price FLOAT,
    weight FLOAT(5,2),
    precise_value DOUBLE(10,6)
);

INSERT INTO float_table VALUES (123.456, 123.45, 123.456789);

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

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;
-- 结果:精确值

4.2 金额存储 #

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

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

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

五、字符串类型 #

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 MariaDB 10.3+ 微秒支持 #

sql
-- MariaDB支持微秒精度
CREATE TABLE microsecond_table (
    id INT PRIMARY KEY,
    created_at DATETIME(6)  -- 6位微秒精度
);

INSERT INTO microsecond_table VALUES (1, '2024-01-15 10:30:00.123456');

SELECT created_at FROM microsecond_table;
-- 结果:2024-01-15 10:30:00.123456

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=周一)

-- MariaDB特有函数
SELECT TO_SECONDS('2024-01-15');  -- 转换为秒数
SELECT SECONDS_TO_TIME(3600);      -- 秒数转时间

七、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 MariaDB增强JSON函数 #

sql
-- MariaDB 10.5+ JSON函数增强

-- JSON_VALUE(提取标量值)
SELECT JSON_VALUE('{"name": "John"}', '$.name');
-- 结果:John

-- JSON_TABLE(将JSON转为表)
SELECT * FROM JSON_TABLE(
    '[{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]',
    '$[*]' COLUMNS(
        id INT PATH '$.id',
        name VARCHAR(50) PATH '$.name'
    )
) AS jt;

-- JSON_EXISTS(检查路径是否存在)
SELECT JSON_EXISTS('{"a": 1}', '$.a');  -- 1
SELECT JSON_EXISTS('{"a": 1}', '$.b');  -- 0

-- JSON_NORMALIZE(规范化JSON)
SELECT JSON_NORMALIZE('{"b":2,"a":1}');
-- 结果:{"a":1,"b":2}(按键排序)

7.4 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;

-- 创建虚拟列和索引
CREATE TABLE json_indexed (
    id INT PRIMARY KEY,
    data JSON,
    name VARCHAR(100) AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.name'))) STORED,
    INDEX idx_name (name)
);

八、枚举和集合 #

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
CREATE TABLE spatial_table (
    id INT PRIMARY KEY,
    location POINT,
    route LINESTRING,
    area POLYGON,
    geometry GEOMETRY
);

-- 插入点
INSERT INTO spatial_table (id, location) 
VALUES (1, POINT(116.404, 39.915));

-- 插入线
INSERT INTO spatial_table (id, route) 
VALUES (2, LINESTRING(POINT(0,0), POINT(1,1), POINT(2,2)));

-- 插入多边形
INSERT INTO spatial_table (id, area) 
VALUES (3, POLYGON(LINESTRING(POINT(0,0), POINT(0,1), POINT(1,1), POINT(1,0), POINT(0,0))));

10.2 空间函数 #

sql
-- 计算距离
SELECT ST_Distance(
    POINT(116.404, 39.915),
    POINT(121.474, 31.230)
);

-- 判断包含关系
SELECT ST_Contains(
    POLYGON(LINESTRING(POINT(0,0), POINT(0,2), POINT(2,2), POINT(2,0), POINT(0,0))),
    POINT(1,1)
);

-- 获取边界
SELECT ST_Boundary(
    POLYGON(LINESTRING(POINT(0,0), POINT(0,1), POINT(1,1), POINT(1,0), POINT(0,0)))
);

十一、UUID类型 #

11.1 MariaDB 10.7+ UUID类型 #

sql
-- MariaDB 10.7+ 原生UUID类型
CREATE TABLE uuid_table (
    id UUID DEFAULT UUID(),
    name VARCHAR(100)
);

INSERT INTO uuid_table (name) VALUES ('John');

SELECT * FROM uuid_table;
-- id: 550e8400-e29b-41d4-a716-446655440000

-- UUID函数
SELECT UUID();
SELECT UUID_SHORT();
SELECT SYS_GUID();  -- Oracle兼容

11.2 旧版本UUID处理 #

sql
-- MariaDB 10.6及以下版本
CREATE TABLE uuid_compat (
    id CHAR(36) DEFAULT UUID(),
    name VARCHAR(100)
);

-- 或使用BINARY(16)存储
CREATE TABLE uuid_binary (
    id BINARY(16) DEFAULT UNHEX(REPLACE(UUID(), '-', '')),
    name VARCHAR(100)
);

-- 查询时转换
SELECT HEX(id) FROM uuid_binary;
SELECT UUID_FROM_BIN(id) FROM uuid_binary;  -- MariaDB 10.8+

十二、类型转换 #

12.1 隐式转换 #

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

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

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

12.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);

十三、类型选择建议 #

13.1 数值类型选择 #

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

13.2 字符串类型选择 #

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

13.3 时间类型选择 #

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

十四、总结 #

数据类型选择要点:

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

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

最后更新:2026-03-27