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函数。


相关推荐
恒悦sunsite几秒前
Ubuntu之apt安装ClickHouse数据库
数据库·clickhouse·ubuntu·列式存储·8123
奥尔特星云大使31 分钟前
MySQL 慢查询日志slow query log
android·数据库·mysql·adb·慢日志·slow query log
来自宇宙的曹先生35 分钟前
MySQL 存储引擎 API
数据库·mysql
间彧1 小时前
MySQL Performance Schema详解与实战应用
数据库
间彧1 小时前
MySQL Exporter采集的关键指标有哪些,如何解读这些指标?
数据库
weixin_446260851 小时前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
mpHH1 小时前
babelfish for postgresql 分析--todo
数据库·postgresql
zizisuo1 小时前
解决在使用Lombok时maven install 找不到符号的问题
java·数据库·maven
程序边界3 小时前
国产之光!金仓数据库KingbaseES Oracle兼容性深度体验大赏
数据库·oracle
A阳俊yi3 小时前
Spring——声明式事务
java·数据库·spring