目录
[1 SQLite的类型概述](#1 SQLite的类型概述)
[1.1 存储类(Storage Classes)](#1.1 存储类(Storage Classes))
[1.2 类型亲和性(Type Affinity)](#1.2 类型亲和性(Type Affinity))
[2 类型亲和性分配规则](#2 类型亲和性分配规则)
[3 数据类型详细说明](#3 数据类型详细说明)
[3.1 INTEGER类型](#3.1 INTEGER类型)
[3.2 REAL类型](#3.2 REAL类型)
[3.3 TEXT类型](#3.3 TEXT类型)
[3.4 BLOB类型](#3.4 BLOB类型)
[3.5 NULL类型](#3.5 NULL类型)
[3.6 NUMERIC类型](#3.6 NUMERIC类型)
[4 特殊类型和类型转换](#4 特殊类型和类型转换)
[4.1 BOOLEAN](#4.1 BOOLEAN)
[4.2 DATE, DATETIME, TIMESTAMP](#4.2 DATE, DATETIME, TIMESTAMP)
[4.3 DECIMAL和精确数值](#4.3 DECIMAL和精确数值)
[5 类型转换和兼容性](#5 类型转换和兼容性)
[5.2 显式类型转换](#5.2 显式类型转换)
[5.2 隐式类型转换规则](#5.2 隐式类型转换规则)
[5.3 类型灵活性示例](#5.3 类型灵活性示例)
[6 数据类型的实际应用示例](#6 数据类型的实际应用示例)
[6.1 主键和ROWID](#6.1 主键和ROWID)
[6.2 处理二进制数据(BLOB)](#6.2 处理二进制数据(BLOB))
[6.3 存储和查询JSON数据](#6.3 存储和查询JSON数据)
[6.4 日期时间处理](#6.4 日期时间处理)
[6.5 高效存储大表的考虑](#6.5 高效存储大表的考虑)
[7 数据类型的最佳实践](#7 数据类型的最佳实践)
[8 SQLite类型系统的优缺点](#8 SQLite类型系统的优缺点)
[8.1 优点](#8.1 优点)
[8.2 缺点](#8.2 缺点)
[9 总结](#9 总结)
SQLite采用了一种不同于大多数其他SQL数据库的类型系统,称为"动态类型系统"或"存储类系统"。下面将详细介绍SQLite的数据类型体系、类型亲和性、类型存储及其使用特点。
1 SQLite的类型概述
1.1 存储类(Storage Classes)
SQLite有5种基本存储类:
存储类 | 描述 | 存储方式 |
---|---|---|
NULL | 表示空值 | NULL |
INTEGER | 有符号整数 | 1, 2, 3, 4, 6或8字节,取决于存储的数值大小 |
REAL | 浮点数 | 8字节的IEEE浮点数 |
TEXT | 文本字符串 | UTF-8、UTF-16BE或UTF-16LE编码 |
BLOB | 二进制大对象 | 按照输入存储(完全保留) |
1.2 类型亲和性(Type Affinity)
当创建表时,SQLite会为每列分配一种类型亲和性。类型亲和性决定了SQLite如何尝试转换存储的值:
INTEGER - 倾向于将数据存储为INTEGER
TEXT - 倾向于将数据存储为TEXT
REAL - 倾向于将数据存储为REAL
NUMERIC - 尝试存储为INTEGER或REAL;如果不行则为TEXT
BLOB - 不做任何类型转换,按原样存储
2 类型亲和性分配规则
SQLite根据列的声明类型决定其类型亲和性,规则如下:
INTEGER亲和性:如果类型包含字符串"INT"(不区分大小写)
- 例如:INT, INTEGER, BIGINT, SMALLINT, TINYINT
TEXT亲和性:如果类型包含以下任一字符串(不区分大小写):
"CHAR", "CLOB", "TEXT"
例如:VARCHAR, NCHAR, CLOB, TEXT
BLOB亲和性:仅当列的声明类型为"BLOB"(不区分大小写)
REAL亲和性:如果类型包含以下任一字符串(不区分大小写):
"REAL", "FLOA", "DOUB"
例如:REAL, FLOAT, DOUBLE, DOUBLE PRECISION
NUMERIC亲和性:所有其他情况,包括:
- NUMERIC, DECIMAL, BOOLEAN, DATE, DATETIME
3 数据类型详细说明
3.1 INTEGER类型
sql
CREATE TABLE example (
id INTEGER PRIMARY KEY,
count INTEGER,
big_num BIGINT,
small_num SMALLINT
);
注意事项:
存储有符号整数值
最大可达8字节(64位),范围:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
可用于主键(特别是INTEGER PRIMARY KEY)
与JavaScript不同,SQLite的INTEGER可以精确表示大整数,不会有精度损失
3.2 REAL类型
sql
CREATE TABLE measurements (
temperature REAL,
distance FLOAT,
calculation DOUBLE
);
注意事项:
存储8字节的IEEE浮点数
范围约为±1.79×10^308,精度为15-16位十进制数字
所有FLOAT, DOUBLE等类型都会映射为REAL
受浮点数固有的精度限制影响
3.3 TEXT类型
sql
CREATE TABLE messages (
message TEXT,
name VARCHAR(100),
description NVARCHAR(200)
);
注意事项:
存储文本字符串,默认为UTF-8编码
也可以存储为UTF-16BE或UTF-16LE
没有固定的长度限制(除了整个数据库的大小限制)
VARCHAR(N)中的长度限制仅作为文档说明,不强制执行
3.4 BLOB类型
sql
CREATE TABLE files (
file_id INTEGER PRIMARY KEY,
file_name TEXT,
file_data BLOB
);
注意事项:
原样存储二进制数据
适用于图像、音频、视频、加密数据等任何二进制内容
不进行任何编码或转换
没有大小限制(除了数据库大小限制)
3.5 NULL类型
sql
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
middle_name TEXT DEFAULT NULL
);
注意事项:
表示缺少值
与其他数据库的NULL类似
NULL是一个特殊值,不等于零、空字符串或任何其他值
3.6 NUMERIC类型
sql
CREATE TABLE financial (
amount NUMERIC,
tax DECIMAL(10,2),
is_completed BOOLEAN,
transaction_date DATE
);
注意事项:
可以存储为INTEGER、REAL或TEXT,具体取决于值
整数值优先存储为INTEGER
非整数数值存储为REAL
不符合数值格式的值存储为TEXT
4 特殊类型和类型转换
4.1 BOOLEAN
SQLite没有专门的布尔类型,通常用以下方式表示:
sql
CREATE TABLE settings (
feature_enabled BOOLEAN -- 实际存储为INTEGER: 0(false)或1(true)
);
注意事项:
存储为INTEGER: 0(false)或1(true)
在查询中,所有非0值和非NULL值都被视为true
4.2 DATE, DATETIME, TIMESTAMP
SQLite没有专门的日期或时间类型,通常以以下方式存储:
sql
CREATE TABLE events (
event_date DATE, -- 实际上是TEXT、REAL或INTEGER
created_at TIMESTAMP, -- 实际上是TEXT、REAL或INTEGER
meeting_time DATETIME -- 实际上是TEXT、REAL或INTEGER
);
常见日期时间存储格式:
- TEXT格式(推荐)- 如 '2023-05-15 15:30:00'
- ISO8601格式: 'YYYY-MM-DD HH:MM:SS.SSS'
- 最便于人类阅读和理解
- INTEGER格式 - Unix时间戳(自1970-01-01 00:00:00 UTC以来的秒数)
- 适合于日期比较和计算
- REAL格式 - Julian日期格式(自公元前4714年起的天数)
- 可以精确到毫秒级别
SQLite提供内置日期函数处理这些格式:
date()
、time()
、datetime()
strftime()
julianday()
4.3 DECIMAL和精确数值
SQLite没有专门的DECIMAL或MONEY类型:
sql
CREATE TABLE financial (
price DECIMAL(10,2) -- 实际上是NUMERIC亲和性
);
对于需要精确计算的财务数据,有两种方案:
-
整数存储:将金额乘以100或10000存储为INTEGER
sql-- 存储$123.45为12345 INSERT INTO financial(price_cents) VALUES (12345); -- 查询时除以100 SELECT price_cents/100.0 AS price FROM financial;
-
TEXT存储:将精确小数存储为TEXT,需要计算时转换
5 类型转换和兼容性
5.2 显式类型转换
sql
-- INTEGER转换
SELECT CAST('123' AS INTEGER); -- 返回123
SELECT CAST(123.45 AS INTEGER); -- 返回123 (截断)
-- REAL转换
SELECT CAST('123.45' AS REAL); -- 返回123.45
SELECT CAST(123 AS REAL); -- 返回123.0
-- TEXT转换
SELECT CAST(123 AS TEXT); -- 返回'123'
SELECT CAST(123.45 AS TEXT); -- 返回'123.45'
5.2 隐式类型转换规则
SQLite会根据上下文自动转换类型:
-
数值上下文中的TEXT
sqlSELECT '123' + 456; -- 579 (TEXT转为INTEGER) SELECT '123.45' + 1; -- 124.45 (TEXT转为REAL)
-
TEXT上下文中的数值
sqlSELECT 123 || 'abc'; -- '123abc' (INTEGER转为TEXT) SELECT 123.45 || 'x'; -- '123.45x' (REAL转为TEXT)
-
比较操作中的混合类型
sqlSELECT 123 = '123'; -- 1 (true,比较前进行转换)
5.3 类型灵活性示例
sql
CREATE TABLE flexible(x);
INSERT INTO flexible VALUES
(NULL),
(42),
(3.14159),
('hello'),
(x'ABCD'); -- BLOB值
SELECT typeof(x), x FROM flexible;
结果:
sql
typeof(x) x
--------- ------
NULL NULL
INTEGER 42
REAL 3.14159
TEXT hello
BLOB ABCD
6 数据类型的实际应用示例
6.1 主键和ROWID
sql
-- 使用INTEGER PRIMARY KEY (推荐)
CREATE TABLE users (
user_id INTEGER PRIMARY KEY, -- 与内部ROWID关联
username TEXT UNIQUE
);
-- 隐式ROWID
CREATE TABLE messages (
content TEXT
-- 自动创建一个隐藏的ROWID列
);
-- 显式禁用ROWID
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT
) WITHOUT ROWID; -- 节省空间,但不自动生成ID
6.2 处理二进制数据(BLOB)
sql
-- 存储图像文件
CREATE TABLE images (
image_id INTEGER PRIMARY KEY,
name TEXT,
data BLOB, -- 存储二进制图像数据
mime_type TEXT
);
-- C#代码示例
// 读取图像到SQLite
byte[] imageData = File.ReadAllBytes("image.jpg");
using (var command = new SQLiteCommand(connection)) {
command.CommandText = "INSERT INTO images(name, data, mime_type) VALUES (@name, @data, @mime)";
command.Parameters.AddWithValue("@name", "sample.jpg");
command.Parameters.AddWithValue("@data", imageData);
command.Parameters.AddWithValue("@mime", "image/jpeg");
command.ExecuteNonQuery();
}
6.3 存储和查询JSON数据
sql
-- 创建包含JSON的表
CREATE TABLE products (
product_id INTEGER PRIMARY KEY,
name TEXT,
attributes TEXT -- 存储JSON数据
);
-- 插入JSON数据
INSERT INTO products(name, attributes)
VALUES ('Smartphone',
'{"color":"black","memory":"128GB","camera":"12MP"}');
-- 使用JSON函数查询(SQLite 3.9.0+)
SELECT name,
json_extract(attributes, '$.color') AS color,
json_extract(attributes, '$.memory') AS memory
FROM products;
-- 使用JSON路径操作符(SQLite 3.38.0+)
SELECT name,
attributes->>'$.color' AS color,
attributes->>'$.memory' AS memory
FROM products;
6.4 日期时间处理
sql
-- 创建日期时间表
CREATE TABLE events (
event_id INTEGER PRIMARY KEY,
title TEXT,
event_date TEXT, -- ISO格式日期
created_at TEXT DEFAULT (datetime('now'))
);
-- 插入日期
INSERT INTO events(title, event_date)
VALUES ('Conference', '2023-12-15 09:00:00');
-- 日期计算和过滤
SELECT title, event_date
FROM events
WHERE date(event_date) > date('now');
-- 日期格式化
SELECT title,
strftime('%Y-%m-%d', event_date) AS date_only,
strftime('%H:%M', event_date) AS time_only
FROM events;
-- 日期差值计算(天数)
SELECT title,
julianday('now') - julianday(event_date) AS days_diff
FROM events;
6.5 高效存储大表的考虑
sql
-- 为大表选择高效数据类型
CREATE TABLE log_entries (
id INTEGER PRIMARY KEY, -- 比BIGINT更节省空间
timestamp INTEGER, -- Unix时间戳比ISO日期字符串更紧凑
level TINYINT, -- 使用更小的整数类型(虽然存储还是INTEGER)
message TEXT -- 可变长度字符串
);
-- 索引对类型的影响
CREATE INDEX idx_timestamp ON log_entries(timestamp);
-- 整数索引通常比文本索引更高效
7 数据类型的最佳实践
-
明确指定类型
sql-- 推荐 CREATE TABLE users ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER, score REAL ); -- 不推荐 CREATE TABLE users ( id, name, age, score );
-
合理使用INTEGER PRIMARY KEY
sql-- 推荐 CREATE TABLE categories ( category_id INTEGER PRIMARY KEY, name TEXT ); -- 不推荐对常用ID列使用TEXT类型 CREATE TABLE categories ( category_id TEXT PRIMARY KEY, -- 更慢,更占空间 name TEXT );
-
日期时间存储策略
sql-- 推荐(可读性好) CREATE TABLE appointments ( appointment_date TEXT DEFAULT (datetime('now', 'localtime')) ); -- 推荐(计算效率高) CREATE TABLE logs ( timestamp INTEGER DEFAULT (strftime('%s', 'now')) );
-
JSON存储与结构化数据的权衡
sql-- 少量属性,经常作为整体访问:使用JSON CREATE TABLE user_preferences ( user_id INTEGER PRIMARY KEY, settings TEXT -- JSON数据 ); -- 频繁查询特定字段:使用结构化表 CREATE TABLE user_preferences_structured ( user_id INTEGER PRIMARY KEY, theme TEXT, notifications BOOLEAN, language TEXT );
-
使用约束增强类型安全
sqlCREATE TABLE employees ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE CHECK(length(email) > 3 AND email LIKE '%@%'), salary REAL CHECK(salary >= 0), department_id INTEGER REFERENCES departments(id) );
8 SQLite类型系统的优缺点
8.1 优点
灵活性:可以存储任何类型的数据到任何列
简单性:不需要像其他数据库那样处理复杂的类型系统
兼容性:容易从其他系统导入数据,不会遇到严格类型不匹配问题
紧凑存储:值按实际需要的空间存储,而不是预分配固定大小
8.2 缺点
类型安全性较低:没有严格的类型检查,可能导致数据一致性问题
隐式转换可能导致意外行为:在操作中类型可能自动转换
与其他SQL数据库不完全兼容:迁移代码时需要注意类型差异
缺少专门的DECIMAL/金融类型:需要应用层面处理精确计算
9 总结
SQLite的数据类型系统虽然简单,但非常灵活且强大:
它提供5种基本存储类型:NULL, INTEGER, REAL, TEXT, BLOB
使用类型亲和性机制来尝试转换数据到合适的存储类型
不强制执行类型约束,但通过CHECK约束可以实现类型安全
灵活性使其非常容易使用,但需要在应用层面确保数据一致性
相比其他关系型数据库,SQLite的类型系统更加灵活,但也需要开发者更加谨慎地使用,确保数据的一致性和完整性。特别是在处理财务数据、精确计算和日期时间时,需要采取适当的存储策略。以上就是SQLite数据类型的全部内容啦,期待我们下期的相遇,下期将介绍SQLite的函数以及如何使用SQLite函数。