SQLite数据类型 #
一、SQLite类型系统概述 #
1.1 动态类型系统 #
SQLite 使用独特的动态类型系统,与其他数据库的静态类型系统不同:
sql
-- SQLite 允许在同一列存储不同类型的数据
CREATE TABLE test (value);
INSERT INTO test VALUES (123); -- 整数
INSERT INTO test VALUES (3.14); -- 浮点数
INSERT INTO test VALUES ('Hello'); -- 文本
INSERT INTO test VALUES (X'010203'); -- BLOB
INSERT INTO test VALUES (NULL); -- NULL
SELECT typeof(value), value FROM test;
1.2 与静态类型系统的区别 #
sql
-- 静态类型系统(如MySQL)
-- 列类型严格限制存储的数据类型
-- SQLite 动态类型系统
-- 列类型只是建议,实际存储类型由值决定
CREATE TABLE users (
name TEXT, -- 建议存储文本
age INTEGER -- 建议存储整数
);
-- SQLite 允许这样(但不推荐)
INSERT INTO users VALUES (123, 'Hello'); -- 可以插入,但类型会被转换
二、存储类 #
2.1 五种存储类 #
SQLite 只有 5 种基本存储类:
| 存储类 | 说明 | 示例 |
|---|---|---|
| NULL | 空值 | NULL |
| INTEGER | 有符号整数 | 1, -123, 9223372036854775807 |
| REAL | 浮点数 | 3.14, -1.5e10 |
| TEXT | UTF-8/UTF-16 字符串 | ‘Hello’, ‘你好’ |
| BLOB | 二进制数据 | X’01020304’ |
2.2 NULL 存储类 #
sql
-- NULL 表示缺失或未知的值
CREATE TABLE test (id INTEGER, value TEXT);
INSERT INTO test VALUES (1, NULL);
-- NULL 的特点
SELECT NULL = NULL; -- 结果是 NULL
SELECT NULL IS NULL; -- 结果是 1
SELECT NULL IS NOT NULL;-- 结果是 0
-- NULL 在运算中
SELECT NULL + 1; -- 结果是 NULL
SELECT NULL || 'text'; -- 结果是 NULL
SELECT COALESCE(NULL, 'default'); -- 结果是 'default'
2.3 INTEGER 存储类 #
sql
-- INTEGER 存储有符号整数
-- 根据值的大小自动选择存储大小
-- 存储大小:
-- 1字节:-128 到 127
-- 2字节:-32768 到 32767
-- 3字节:-8388608 到 8388607
-- 4字节:-2147483648 到 2147483647
-- 6字节:-140737488355328 到 140737488355327
-- 8字节:-9223372036854775808 到 9223372036854775807
CREATE TABLE numbers (value INTEGER);
INSERT INTO numbers VALUES (127); -- 1字节
INSERT INTO numbers VALUES (32767); -- 2字节
INSERT INTO numbers VALUES (2147483647); -- 4字节
INSERT INTO numbers VALUES (9223372036854775807); -- 8字节
-- 查看存储类型
SELECT value, typeof(value) FROM numbers;
2.4 REAL 存储类 #
sql
-- REAL 存储 8 字节 IEEE 浮点数
CREATE TABLE floats (value REAL);
INSERT INTO floats VALUES (3.14);
INSERT INTO floats VALUES (-1.5e10);
INSERT INTO floats VALUES (1.5E-10);
-- 整数可以存储为 REAL
INSERT INTO floats VALUES (100); -- 存储为 100.0
SELECT value, typeof(value) FROM floats;
2.5 TEXT 存储类 #
sql
-- TEXT 存储字符串
-- 使用数据库编码(UTF-8 或 UTF-16)
CREATE TABLE texts (value TEXT);
INSERT INTO texts VALUES ('Hello World');
INSERT INTO texts VALUES ('你好世界');
INSERT INTO texts VALUES ('🎉 Emoji');
-- 字符串长度限制:10亿字节
SELECT value, typeof(value), length(value) FROM texts;
2.6 BLOB 存储类 #
sql
-- BLOB 存储二进制数据
-- 完全按输入存储,不做任何转换
CREATE TABLE blobs (value BLOB);
INSERT INTO blobs VALUES (X'0102030405');
INSERT INTO blobs VALUES (X'48656C6C6F'); -- 'Hello' 的十六进制
-- 使用 zeroblob 创建指定大小的 BLOB
INSERT INTO blobs VALUES (zeroblob(100)); -- 100字节的零
SELECT value, typeof(value), length(value) FROM blobs;
三、类型亲和性 #
3.1 什么是类型亲和性 #
sql
-- 类型亲和性决定 SQLite 如何处理列的数据类型
-- 当声明列类型时,SQLite 会根据类型名称确定亲和性
CREATE TABLE example (
col1 INT, -- INTEGER 亲和性
col2 VARCHAR(255), -- TEXT 亲和性
col3 FLOAT, -- REAL 亲和性
col4 BLOB, -- BLOB 亲和性
col5 NUMERIC -- NUMERIC 亲和性
);
3.2 五种类型亲和性 #
| 亲和性 | 说明 | 声明类型示例 |
|---|---|---|
| INTEGER | 优先存储为整数 | INT, INTEGER, BIGINT |
| TEXT | 优先存储为文本 | TEXT, CHAR, VARCHAR |
| BLOB | 不做类型转换 | BLOB, 无类型声明 |
| REAL | 优先存储为浮点数 | REAL, DOUBLE, FLOAT |
| NUMERIC | 智能选择类型 | NUMERIC, DECIMAL, BOOLEAN |
3.3 INTEGER 亲和性 #
sql
-- INTEGER 亲和性的列优先存储整数
CREATE TABLE int_test (
col INT,
col2 INTEGER,
col3 BIGINT,
col4 SMALLINT,
col5 TINYINT,
col6 MEDIUMINT
);
-- 插入整数
INSERT INTO int_test (col) VALUES (123);
SELECT typeof(col) FROM int_test; -- integer
-- 插入浮点数(会转换为整数)
INSERT INTO int_test (col) VALUES (3.14);
SELECT col, typeof(col) FROM int_test WHERE col = 3; -- 3, integer
-- 插入文本数字
INSERT INTO int_test (col) VALUES ('456');
SELECT col, typeof(col) FROM int_test WHERE col = 456; -- 456, integer
3.4 TEXT 亲和性 #
sql
-- TEXT 亲和性的列优先存储文本
CREATE TABLE text_test (
col TEXT,
col2 VARCHAR(255),
col3 CHAR(20),
col4 CLOB
);
-- 插入文本
INSERT INTO text_test (col) VALUES ('Hello');
SELECT typeof(col) FROM text_test; -- text
-- 插入数字(会转换为文本)
INSERT INTO text_test (col) VALUES (123);
SELECT col, typeof(col) FROM text_test WHERE col = '123'; -- 123, text
-- 插入浮点数
INSERT INTO text_test (col) VALUES (3.14);
SELECT col, typeof(col) FROM text_test WHERE col = '3.14'; -- 3.14, text
3.5 BLOB 亲和性 #
sql
-- BLOB 亲和性的列不做类型转换
CREATE TABLE blob_test (
col BLOB,
col2 -- 无类型声明也是 BLOB 亲和性
);
-- 插入什么就存储什么
INSERT INTO blob_test VALUES (123, 123);
INSERT INTO blob_test VALUES ('Hello', 'Hello');
INSERT INTO blob_test VALUES (3.14, 3.14);
INSERT INTO blob_test VALUES (X'010203', X'010203');
SELECT typeof(col), typeof(col2) FROM blob_test;
-- integer, integer
-- text, text
-- real, real
-- blob, blob
3.6 REAL 亲和性 #
sql
-- REAL 亲和性的列优先存储浮点数
CREATE TABLE real_test (
col REAL,
col2 DOUBLE,
col3 FLOAT
);
-- 插入浮点数
INSERT INTO real_test (col) VALUES (3.14);
SELECT typeof(col) FROM real_test; -- real
-- 插入整数(会转换为浮点数)
INSERT INTO real_test (col) VALUES (100);
SELECT col, typeof(col) FROM real_test WHERE col = 100; -- 100.0, real
3.7 NUMERIC 亲和性 #
sql
-- NUMERIC 亲和性智能选择存储类型
CREATE TABLE numeric_test (
col NUMERIC,
col2 DECIMAL(10,2),
col3 BOOLEAN,
col4 DATE,
col5 DATETIME
);
-- 插入整数
INSERT INTO numeric_test (col) VALUES (123);
SELECT typeof(col) FROM numeric_test; -- integer
-- 插入浮点数
INSERT INTO numeric_test (col) VALUES (3.14);
SELECT typeof(col) FROM numeric_test WHERE col = 3.14; -- real
-- 插入文本数字
INSERT INTO numeric_test (col) VALUES ('456');
SELECT typeof(col) FROM numeric_test WHERE col = 456; -- integer
-- 插入无法转换的文本
INSERT INTO numeric_test (col) VALUES ('Hello');
SELECT typeof(col) FROM numeric_test WHERE col = 'Hello'; -- text
-- BOOLEAN 类型
INSERT INTO numeric_test (col3) VALUES (TRUE); -- 存储为 1
INSERT INTO numeric_test (col3) VALUES (FALSE); -- 存储为 0
SELECT col3, typeof(col3) FROM numeric_test; -- 1, integer / 0, integer
四、类型转换规则 #
4.1 存储时的类型转换 #
sql
-- 类型亲和性决定存储时的转换规则
-- 规则1:BLOB 亲和性 - 不转换
CREATE TABLE t1 (col BLOB);
INSERT INTO t1 VALUES (123); -- 存储为 integer
INSERT INTO t1 VALUES ('text'); -- 存储为 text
-- 规则2:TEXT 亲和性 - 转换为文本
CREATE TABLE t2 (col TEXT);
INSERT INTO t2 VALUES (123); -- 转换为 '123'
INSERT INTO t2 VALUES (3.14); -- 转换为 '3.14'
-- 规则3:INTEGER 亲和性 - 转换为整数
CREATE TABLE t3 (col INTEGER);
INSERT INTO t3 VALUES (3.14); -- 转换为 3
INSERT INTO t3 VALUES ('123'); -- 转换为 123
-- 规则4:REAL 亲和性 - 转换为浮点数
CREATE TABLE t4 (col REAL);
INSERT INTO t4 VALUES (123); -- 转换为 123.0
INSERT INTO t4 VALUES ('3.14'); -- 转换为 3.14
-- 规则5:NUMERIC 亲和性 - 智能选择
CREATE TABLE t5 (col NUMERIC);
INSERT INTO t5 VALUES ('123'); -- 转换为 integer 123
INSERT INTO t5 VALUES ('3.14'); -- 转换为 real 3.14
INSERT INTO t5 VALUES ('hello'); -- 保持 text 'hello'
4.2 比较时的类型转换 #
sql
-- 比较操作时的类型转换规则
-- 相同类型比较
SELECT 1 = 1; -- 1 (integer = integer)
SELECT 'a' = 'a'; -- 1 (text = text)
-- 不同类型比较
-- 规则:NULL < BLOB < TEXT < INTEGER < REAL
-- NULL 比较
SELECT NULL = 1; -- NULL
SELECT NULL < 1; -- NULL
SELECT NULL IS NULL; -- 1
-- INTEGER 和 REAL 比较
SELECT 1 = 1.0; -- 1 (数值比较)
SELECT 1 < 1.5; -- 1
-- TEXT 和 INTEGER 比较
SELECT '1' = 1; -- 1 (文本转换为数值)
SELECT '1.5' = 1.5; -- 1
SELECT 'abc' = 0; -- 0 (文本转换为0,但不相等)
-- BLOB 比较
SELECT X'61' = 'a'; -- 0 (BLOB 和 TEXT 不相等)
4.3 显式类型转换 #
sql
-- CAST 表达式
-- 转换为 INTEGER
SELECT CAST('123' AS INTEGER); -- 123
SELECT CAST(3.14 AS INTEGER); -- 3
SELECT CAST('abc' AS INTEGER); -- 0
-- 转换为 REAL
SELECT CAST('3.14' AS REAL); -- 3.14
SELECT CAST(123 AS REAL); -- 123.0
-- 转换为 TEXT
SELECT CAST(123 AS TEXT); -- '123'
SELECT CAST(3.14 AS TEXT); -- '3.14'
SELECT CAST(X'48656C6C6F' AS TEXT); -- 'Hello'
-- 转换为 BLOB
SELECT CAST('Hello' AS BLOB); -- X'48656C6C6F'
-- 转换为 NUMERIC
SELECT CAST('123' AS NUMERIC); -- 123 (integer)
SELECT CAST('3.14' AS NUMERIC); -- 3.14 (real)
五、typeof函数 #
5.1 检查存储类型 #
sql
-- typeof() 返回值的存储类型
SELECT typeof(NULL); -- 'null'
SELECT typeof(123); -- 'integer'
SELECT typeof(3.14); -- 'real'
SELECT typeof('Hello'); -- 'text'
SELECT typeof(X'0102'); -- 'blob'
-- 检查列中的实际存储类型
CREATE TABLE mixed (value);
INSERT INTO mixed VALUES (123);
INSERT INTO mixed VALUES (3.14);
INSERT INTO mixed VALUES ('Hello');
INSERT INTO mixed VALUES (X'0102');
INSERT INTO mixed VALUES (NULL);
SELECT value, typeof(value) FROM mixed;
六、特殊数据类型 #
6.1 布尔类型 #
sql
-- SQLite 没有独立的布尔类型
-- 使用 INTEGER 存储:0 = false, 1 = true
CREATE TABLE flags (
id INTEGER PRIMARY KEY,
is_active BOOLEAN DEFAULT 1,
has_permission BOOLEAN DEFAULT 0
);
-- 插入布尔值
INSERT INTO flags (is_active, has_permission) VALUES (TRUE, FALSE);
INSERT INTO flags (is_active, has_permission) VALUES (1, 0);
INSERT INTO flags (is_active, has_permission) VALUES ('true', 'false');
SELECT
id,
is_active,
typeof(is_active),
has_permission,
typeof(has_permission)
FROM flags;
-- 布尔比较
SELECT * FROM flags WHERE is_active = TRUE;
SELECT * FROM flags WHERE is_active = 1;
SELECT * FROM flags WHERE is_active; -- 简写
6.2 日期时间类型 #
sql
-- SQLite 没有独立的日期时间类型
-- 使用 TEXT, REAL 或 INTEGER 存储
CREATE TABLE events (
id INTEGER PRIMARY KEY,
name TEXT,
-- TEXT 格式:'YYYY-MM-DD HH:MM:SS'
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
-- REAL 格式:Julian day number
julian_date REAL,
-- INTEGER 格式:Unix timestamp
unix_time INTEGER
);
-- 插入日期时间
INSERT INTO events (name, created_at, julian_date, unix_time)
VALUES (
'Event 1',
'2024-01-15 10:30:00',
julianday('2024-01-15 10:30:00'),
strftime('%s', '2024-01-15 10:30:00')
);
-- 日期时间函数
SELECT date('now'); -- 当前日期
SELECT time('now'); -- 当前时间
SELECT datetime('now'); -- 当前日期时间
SELECT julianday('now'); -- Julian day
SELECT strftime('%s', 'now'); -- Unix timestamp
-- 日期计算
SELECT date('now', '+1 day'); -- 明天
SELECT date('now', '-7 days'); -- 7天前
SELECT date('now', '+1 month'); -- 下个月
SELECT datetime('now', '+1 hour'); -- 1小时后
-- 日期格式化
SELECT strftime('%Y-%m-%d', 'now'); -- 2024-01-15
SELECT strftime('%H:%M:%S', 'now'); -- 10:30:00
SELECT strftime('%Y年%m月%d日', 'now'); -- 2024年01月15日
6.3 JSON类型 #
sql
-- SQLite 3.38+ 内置 JSON 支持
-- JSON 数据存储为 TEXT
CREATE TABLE documents (
id INTEGER PRIMARY KEY,
data JSON
);
-- 插入 JSON 数据
INSERT INTO documents (data) VALUES ('{"name": "Alice", "age": 25}');
INSERT INTO documents (data) VALUES ('[1, 2, 3, 4, 5]');
-- JSON 函数
SELECT json_extract(data, '$.name') FROM documents;
SELECT json_extract(data, '$[0]') FROM documents WHERE id = 2;
-- 创建 JSON
SELECT json_object('name', 'Alice', 'age', 25);
SELECT json_array(1, 2, 3, 4, 5);
七、类型判断函数 #
7.1 typeof函数 #
sql
-- typeof() 返回存储类型名称
SELECT typeof(123); -- 'integer'
SELECT typeof(3.14); -- 'real'
SELECT typeof('text'); -- 'text'
SELECT typeof(X'0102'); -- 'blob'
SELECT typeof(NULL); -- 'null'
7.2 类型检查函数 #
sql
-- SQLite 没有内置的 IS_INTEGER 等函数
-- 可以使用 typeof 实现
SELECT
value,
CASE typeof(value)
WHEN 'integer' THEN '是整数'
WHEN 'real' THEN '是浮点数'
WHEN 'text' THEN '是文本'
WHEN 'blob' THEN '是二进制'
ELSE '是NULL'
END AS type_desc
FROM test_table;
八、类型相关常见问题 #
8.1 字符串与数字比较 #
sql
-- 注意:字符串与数字比较时,字符串会转换为数字
-- 创建测试表
CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT);
INSERT INTO test (value) VALUES ('123');
INSERT INTO test (value) VALUES ('abc');
INSERT INTO test (value) VALUES ('123abc');
-- 查询
SELECT * FROM test WHERE value = 123;
-- 返回:id=1 ('123' 转换为 123)
-- 返回:id=3 ('123abc' 转换为 123)
-- 解决方案:显式比较字符串
SELECT * FROM test WHERE value = '123';
-- 只返回:id=1
8.2 主键类型 #
sql
-- INTEGER PRIMARY KEY 是特殊的
-- 它是 ROWID 的别名
CREATE TABLE users (
id INTEGER PRIMARY KEY, -- 自增主键
name TEXT
);
-- AUTOINCREMENT 可选
CREATE TABLE users2 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
-- 区别:
-- INTEGER PRIMARY KEY:重用已删除的ID
-- INTEGER PRIMARY KEY AUTOINCREMENT:永不重用ID
8.3 精度问题 #
sql
-- 浮点数精度问题
SELECT 0.1 + 0.2; -- 0.30000000000000004
SELECT 0.1 + 0.2 = 0.3; -- 0 (不相等!)
-- 解决方案:使用 ROUND
SELECT ROUND(0.1 + 0.2, 2); -- 0.3
SELECT ROUND(0.1 + 0.2, 2) = 0.3; -- 1
-- 或使用整数存储金额
-- 存储分而不是元
CREATE TABLE prices (
id INTEGER PRIMARY KEY,
price_cents INTEGER -- 以分为单位
);
九、总结 #
存储类对比 #
| 存储类 | 说明 | 示例 |
|---|---|---|
| NULL | 空值 | NULL |
| INTEGER | 整数 | 1, -123 |
| REAL | 浮点数 | 3.14, 1e10 |
| TEXT | 文本 | ‘Hello’ |
| BLOB | 二进制 | X’0102’ |
类型亲和性规则 #
| 亲和性 | 声明类型包含 | 转换行为 |
|---|---|---|
| INTEGER | INT, INTEGER, BIGINT等 | 优先转换为整数 |
| TEXT | TEXT, CHAR, VARCHAR等 | 优先转换为文本 |
| BLOB | BLOB, 无类型 | 不做转换 |
| REAL | REAL, DOUBLE, FLOAT | 优先转换为浮点数 |
| NUMERIC | NUMERIC, DECIMAL等 | 智能选择类型 |
最佳实践 #
- 使用明确的类型声明
- 保持数据类型一致性
- 使用 CAST 进行显式转换
- 注意浮点数精度问题
- 使用 typeof 检查实际类型
下一步,让我们学习数据库操作!
最后更新:2026-03-27