SQLite数据类型

目录

[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如何尝试转换存储的值:

  1. INTEGER - 倾向于将数据存储为INTEGER

  2. TEXT - 倾向于将数据存储为TEXT

  3. REAL - 倾向于将数据存储为REAL

  4. NUMERIC - 尝试存储为INTEGER或REAL;如果不行则为TEXT

  5. BLOB - 不做任何类型转换,按原样存储

2 类型亲和性分配规则

SQLite根据列的声明类型决定其类型亲和性,规则如下:

  1. INTEGER亲和性:如果类型包含字符串"INT"(不区分大小写)

    • 例如:INT, INTEGER, BIGINT, SMALLINT, TINYINT
  2. TEXT亲和性:如果类型包含以下任一字符串(不区分大小写):

    • "CHAR", "CLOB", "TEXT"

    • 例如:VARCHAR, NCHAR, CLOB, TEXT

  3. BLOB亲和性:仅当列的声明类型为"BLOB"(不区分大小写)

  4. REAL亲和性:如果类型包含以下任一字符串(不区分大小写):

    • "REAL", "FLOA", "DOUB"

    • 例如:REAL, FLOAT, DOUBLE, DOUBLE PRECISION

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

常见日期时间存储格式:

  1. TEXT格式(推荐)- 如 '2023-05-15 15:30:00'
  • ISO8601格式: 'YYYY-MM-DD HH:MM:SS.SSS'
  • 最便于人类阅读和理解
  1. INTEGER格式 - Unix时间戳(自1970-01-01 00:00:00 UTC以来的秒数)
  • 适合于日期比较和计算
  1. REAL格式 - Julian日期格式(自公元前4714年起的天数)
  • 可以精确到毫秒级别

SQLite提供内置日期函数处理这些格式:

  • date()time()datetime()

  • strftime()

  • julianday()

4.3 DECIMAL和精确数值

SQLite没有专门的DECIMAL或MONEY类型:

sql 复制代码
CREATE TABLE financial (
    price DECIMAL(10,2)  -- 实际上是NUMERIC亲和性
);

对于需要精确计算的财务数据,有两种方案:

  1. 整数存储:将金额乘以100或10000存储为INTEGER

    sql 复制代码
    -- 存储$123.45为12345
    INSERT INTO financial(price_cents) VALUES (12345);
    -- 查询时除以100
    SELECT price_cents/100.0 AS price FROM financial;
  2. 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会根据上下文自动转换类型:

  1. 数值上下文中的TEXT

    sql 复制代码
    SELECT '123' + 456;  -- 579 (TEXT转为INTEGER)
    SELECT '123.45' + 1; -- 124.45 (TEXT转为REAL)
  2. TEXT上下文中的数值

    sql 复制代码
    SELECT 123 || 'abc';  -- '123abc' (INTEGER转为TEXT)
    SELECT 123.45 || 'x'; -- '123.45x' (REAL转为TEXT)
  3. 比较操作中的混合类型

    sql 复制代码
    SELECT 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 数据类型的最佳实践

  1. 明确指定类型

    sql 复制代码
    -- 推荐
    CREATE TABLE users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        age INTEGER,
        score REAL
    );
    ​
    -- 不推荐
    CREATE TABLE users (
        id,
        name,
        age,
        score
    );
  2. 合理使用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
    );
  3. 日期时间存储策略

    sql 复制代码
    -- 推荐(可读性好)
    CREATE TABLE appointments (
        appointment_date TEXT DEFAULT (datetime('now', 'localtime'))
    );
    ​
    -- 推荐(计算效率高)
    CREATE TABLE logs (
        timestamp INTEGER DEFAULT (strftime('%s', 'now'))
    );
  4. 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
    );
  5. 使用约束增强类型安全

    sql 复制代码
    CREATE 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 优点

  1. 灵活性:可以存储任何类型的数据到任何列

  2. 简单性:不需要像其他数据库那样处理复杂的类型系统

  3. 兼容性:容易从其他系统导入数据,不会遇到严格类型不匹配问题

  4. 紧凑存储:值按实际需要的空间存储,而不是预分配固定大小

8.2 缺点

  1. 类型安全性较低:没有严格的类型检查,可能导致数据一致性问题

  2. 隐式转换可能导致意外行为:在操作中类型可能自动转换

  3. 与其他SQL数据库不完全兼容:迁移代码时需要注意类型差异

  4. 缺少专门的DECIMAL/金融类型:需要应用层面处理精确计算

9 总结

SQLite的数据类型系统虽然简单,但非常灵活且强大:

  • 它提供5种基本存储类型:NULL, INTEGER, REAL, TEXT, BLOB

  • 使用类型亲和性机制来尝试转换数据到合适的存储类型

  • 不强制执行类型约束,但通过CHECK约束可以实现类型安全

  • 灵活性使其非常容易使用,但需要在应用层面确保数据一致性

相比其他关系型数据库,SQLite的类型系统更加灵活,但也需要开发者更加谨慎地使用,确保数据的一致性和完整性。特别是在处理财务数据、精确计算和日期时间时,需要采取适当的存储策略。以上就是SQLite数据类型的全部内容啦,期待我们下期的相遇,下期将介绍SQLite的函数以及如何使用SQLite函数。


相关推荐
auspicious航1 小时前
PostgreSQL 常用SQL操作命令
数据库·sql·postgresql
Ten peaches1 小时前
苍穹外卖(订单状态定时处理、来单提醒和客户催单)
java·数据库·sql·springboot
gbase_lmax1 小时前
gbase8s数据库 tcp连接不同阶段的超时处理
网络·数据库·网络协议·tcp/ip
Aliano2172 小时前
Pinecone向量库 VS Redis
数据库·redis·缓存·pinecone向量库
爬呀爬的水滴2 小时前
02 mysql 管理(Windows版)
数据库·mysql
IT成长日记2 小时前
【Hive入门】Hive增量数据导入:基于Sqoop的关系型数据库同步方案深度解析
数据库·hive·sqoop·关系型数据库同步·增量数据导入
芯辰则吉--模拟芯片2 小时前
模拟Sch LVS Sch 方法
服务器·数据库·lvs
weixin_437044642 小时前
JumpServer批量添加资产
数据库·mysql
cyhysr2 小时前
oracle 触发器与commit的先后执行顺序
数据库·oracle
钢铁男儿2 小时前
深入解析C#参数传递:值参数 vs 引用参数
java·开发语言·c#