SQLite表操作 #

一、表概述 #

1.1 SQLite表特点 #

sql
-- SQLite 表的特点:
-- 1. 每个表存储在 B-Tree 结构中
-- 2. 支持 ROWID(隐式主键)
-- 3. 支持 WITHOUT ROWID 表
-- 4. 支持临时表
-- 5. 支持虚拟表

-- 表类型:
-- 1. 普通表 - 持久存储
-- 2. 临时表 - 会话期间存在
-- 3. 虚拟表 - 由代码实现

1.2 表命名规范 #

sql
-- 推荐命名规范
-- 1. 使用小写字母
-- 2. 使用下划线分隔
-- 3. 使用复数形式
-- 4. 避免使用保留字

-- 好的命名
users
user_orders
product_categories
order_items

-- 不好的命名
Users          -- 大写
userOrders     -- 驼峰
user-orders    -- 连字符
order          -- 单数

二、创建表 #

2.1 基本语法 #

sql
-- CREATE TABLE 基本语法
CREATE TABLE table_name (
    column1 datatype [constraints],
    column2 datatype [constraints],
    ...
    [table_constraints]
);

-- 示例:创建用户表
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE,
    age INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

2.2 列定义 #

sql
-- 完整的列定义语法
-- column_name datatype [constraints]

CREATE TABLE products (
    -- 列名 + 数据类型
    id INTEGER,
    
    -- 带约束的列
    name TEXT NOT NULL,
    
    -- 带默认值
    status INTEGER DEFAULT 1,
    
    -- 带多个约束
    email TEXT NOT NULL UNIQUE,
    
    -- 带检查约束
    price REAL CHECK(price >= 0),
    
    -- 带排序规则
    code TEXT COLLATE NOCASE
);

2.3 主键 #

sql
-- 单列主键
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT
);

-- 自增主键
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT
);

-- 复合主键
CREATE TABLE order_items (
    order_id INTEGER,
    product_id INTEGER,
    quantity INTEGER,
    PRIMARY KEY (order_id, product_id)
);

-- PRIMARY KEY 与 ROWID
-- INTEGER PRIMARY KEY 是 ROWID 的别名
-- 其他类型的主键会创建独立的索引
CREATE TABLE users (
    id TEXT PRIMARY KEY,  -- 不是 ROWID 的别名
    name TEXT
);

2.4 外键 #

sql
-- 启用外键约束
PRAGMA foreign_keys = ON;

-- 创建带外键的表
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    total REAL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 外键选项
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    FOREIGN KEY (user_id) REFERENCES users(id)
        ON DELETE CASCADE      -- 删除用户时删除订单
        ON UPDATE CASCADE      -- 更新用户ID时更新订单
);

-- 外键动作
-- ON DELETE/UPDATE:
--   CASCADE  - 级联操作
--   SET NULL - 设置为NULL
--   SET DEFAULT - 设置为默认值
--   RESTRICT - 限制(默认)
--   NO ACTION - 无动作

-- 自引用外键
CREATE TABLE categories (
    id INTEGER PRIMARY KEY,
    name TEXT,
    parent_id INTEGER,
    FOREIGN KEY (parent_id) REFERENCES categories(id)
);

2.5 唯一约束 #

sql
-- 单列唯一约束
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    email TEXT UNIQUE
);

-- 多列唯一约束
CREATE TABLE user_roles (
    user_id INTEGER,
    role_id INTEGER,
    UNIQUE (user_id, role_id)
);

-- 命名唯一约束
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    email TEXT,
    CONSTRAINT uk_users_email UNIQUE (email)
);

2.6 检查约束 #

sql
-- 单列检查约束
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    price REAL CHECK(price >= 0),
    quantity INTEGER CHECK(quantity >= 0)
);

-- 多列检查约束
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    start_date DATE,
    end_date DATE,
    CHECK (end_date > start_date)
);

-- 复杂检查约束
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    age INTEGER,
    email TEXT,
    CHECK (age >= 0 AND age <= 150),
    CHECK (email LIKE '%@%.%')
);

-- 命名检查约束
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    price REAL,
    CONSTRAINT chk_price_positive CHECK (price > 0)
);

2.7 默认值 #

sql
-- 使用常量默认值
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    status INTEGER DEFAULT 1,
    role TEXT DEFAULT 'user'
);

-- 使用函数默认值
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    date DATE DEFAULT (date('now'))
);

-- 使用表达式默认值
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    price REAL,
    discount REAL DEFAULT 0,
    final_price REAL DEFAULT (price * (1 - discount))
);

2.8 非空约束 #

sql
-- NOT NULL 约束
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    phone TEXT  -- 可以为NULL
);

-- NOT NULL 与 DEFAULT 结合
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL DEFAULT 'Anonymous'
);

三、临时表 #

3.1 创建临时表 #

sql
-- TEMPORARY 或 TEMP 关键字
-- 临时表在连接关闭时自动删除

CREATE TEMP TABLE temp_results (
    id INTEGER PRIMARY KEY,
    value TEXT
);

-- 或
CREATE TEMPORARY TABLE temp_results (
    id INTEGER PRIMARY KEY,
    value TEXT
);

-- 临时表只在当前连接可见
-- 存储在 temp 数据库中

3.2 临时表特点 #

sql
-- 临时表特点:
-- 1. 只在当前连接可见
-- 2. 连接关闭时自动删除
-- 3. 存储在临时数据库或内存中
-- 4. 可以创建索引和触发器

-- 使用场景:
-- 1. 复杂查询的中间结果
-- 2. 批量处理的临时存储
-- 3. 会话级别的缓存

四、WITHOUT ROWID表 #

4.1 创建WITHOUT ROWID表 #

sql
-- WITHOUT ROWID 表不使用 ROWID
-- 数据按主键存储在 B-Tree 中

CREATE TABLE users (
    id TEXT PRIMARY KEY,
    name TEXT
) WITHOUT ROWID;

-- 适用场景:
-- 1. 主键是非整数类型
-- 2. 主键较大
-- 3. 需要按主键快速查找

4.2 WITH ROWID vs WITHOUT ROWID #

sql
-- WITH ROWID(默认)
CREATE TABLE with_rowid (
    id TEXT PRIMARY KEY,
    name TEXT
);
-- 存储结构:ROWID -> 数据
-- 主键索引:id -> ROWID

-- WITHOUT ROWID
CREATE TABLE without_rowid (
    id TEXT PRIMARY KEY,
    name TEXT
) WITHOUT ROWID;
-- 存储结构:id -> 数据
-- 无额外的主键索引

-- 选择建议:
-- 使用 WITHOUT ROWID 当:
-- 1. 单行数据较小
-- 2. 主键是非整数
-- 3. 主要按主键查询

-- 使用 WITH ROWID 当:
-- 1. 需要使用 rowid 列
-- 2. 单行数据较大
-- 3. 有多个索引

五、修改表 #

5.1 ALTER TABLE概述 #

sql
-- SQLite 的 ALTER TABLE 功能有限
-- 支持的操作:
-- 1. 重命名表
-- 2. 添加列
-- 3. 重命名列(3.25.0+)
-- 4. 删除列(3.35.5+)

-- 不支持的操作:
-- 1. 修改列类型
-- 2. 添加/删除约束
-- 3. 修改列默认值

5.2 重命名表 #

sql
-- RENAME TO
ALTER TABLE users RENAME TO members;

-- 重命名后,相关对象会自动更新:
-- 1. 索引
-- 2. 触发器
-- 3. 视图

5.3 添加列 #

sql
-- ADD COLUMN
ALTER TABLE users ADD COLUMN age INTEGER;
ALTER TABLE users ADD COLUMN phone TEXT DEFAULT '';

-- 添加列的限制:
-- 1. 不能添加 PRIMARY KEY
-- 2. 不能添加 UNIQUE(除非是 WITHOUT ROWID 表)
-- 3. 不能添加 NOT NULL 且无默认值
-- 4. 不能添加外键约束

-- 可以添加:
ALTER TABLE users ADD COLUMN nickname TEXT;
ALTER TABLE users ADD COLUMN status INTEGER DEFAULT 1;
ALTER TABLE users ADD COLUMN bio TEXT CHECK(length(bio) <= 500);

5.4 重命名列 #

sql
-- SQLite 3.25.0+ 支持
ALTER TABLE users RENAME COLUMN name TO full_name;
ALTER TABLE users RENAME COLUMN created_at TO created_date;

5.5 删除列 #

sql
-- SQLite 3.35.5+ 支持
ALTER TABLE users DROP COLUMN age;
ALTER TABLE users DROP COLUMN phone;

-- 不能删除的列:
-- 1. 主键列
-- 2. 被外键引用的列
-- 3. 索引中的列(需要先删除索引)
-- 4. UNIQUE 约束中的列
-- 5. CHECK 约束中的列

5.6 复杂修改的变通方法 #

sql
-- 对于不支持的修改,使用重建表的方法

-- 步骤:
-- 1. 创建新表
-- 2. 复制数据
-- 3. 删除旧表
-- 4. 重命名新表

-- 示例:修改列类型
BEGIN TRANSACTION;

-- 1. 创建新表
CREATE TABLE users_new (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    age TEXT,  -- 从 INTEGER 改为 TEXT
    email TEXT UNIQUE
);

-- 2. 复制数据
INSERT INTO users_new (id, name, age, email)
SELECT id, name, CAST(age AS TEXT), email FROM users;

-- 3. 删除旧表
DROP TABLE users;

-- 4. 重命名新表
ALTER TABLE users_new RENAME TO users;

-- 5. 重建索引
CREATE INDEX idx_users_email ON users(email);

COMMIT;

六、删除表 #

6.1 DROP TABLE #

sql
-- 基本语法
DROP TABLE table_name;

-- 如果存在则删除
DROP TABLE IF EXISTS users;

-- 删除临时表
DROP TABLE temp.temp_results;

-- 注意:
-- 1. 删除表会同时删除相关索引和触发器
-- 2. 不能删除被外键引用的表(除非先删除外键)
-- 3. 删除后数据无法恢复

6.2 安全删除 #

sql
-- 检查表是否存在
SELECT name FROM sqlite_master WHERE type='table' AND name='users';

-- 条件删除
DROP TABLE IF EXISTS users;

-- 检查外键依赖
SELECT 
    m.name AS table_name,
    p.'from' AS column_name,
    p.'table' AS referenced_table
FROM sqlite_master m
JOIN pragma_foreign_key_list(m.name) p
WHERE p.'table' = 'users';

七、表信息查询 #

7.1 查看表结构 #

sql
-- 命令行方式
.schema users

-- SQL方式
SELECT sql FROM sqlite_master WHERE type='table' AND name='users';

-- 使用 PRAGMA
PRAGMA table_info(users);

-- 输出:
-- cid | name | type | notnull | dflt_value | pk
-- ----|------|------|---------|------------|---
-- 0   | id   | INTEGER | 0    | NULL       | 1
-- 1   | name | TEXT | 0       | NULL       | 0

7.2 查看所有表 #

sql
-- 查看所有表
SELECT name FROM sqlite_master WHERE type='table';

-- 查看所有表和视图
SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view');

-- 查看表数量
SELECT COUNT(*) FROM sqlite_master WHERE type='table';

-- 查看特定前缀的表
SELECT name FROM sqlite_master 
WHERE type='table' AND name LIKE 'order_%';

7.3 查看列信息 #

sql
-- PRAGMA table_info
PRAGMA table_info(users);

-- 输出列:
-- cid: 列ID
-- name: 列名
-- type: 数据类型
-- notnull: 是否非空
-- dflt_value: 默认值
-- pk: 是否主键

-- 查看外键
PRAGMA foreign_key_list(users);

-- 查看索引
PRAGMA index_list(users);

-- 查看索引信息
PRAGMA index_info(idx_users_email);

八、表约束详解 #

8.1 约束类型 #

约束 说明 示例
PRIMARY KEY 主键 id INTEGER PRIMARY KEY
FOREIGN KEY 外键 FOREIGN KEY (user_id) REFERENCES users(id)
UNIQUE 唯一 email TEXT UNIQUE
NOT NULL 非空 name TEXT NOT NULL
CHECK 检查 CHECK (age >= 0)
DEFAULT 默认值 status INTEGER DEFAULT 1

8.2 约束命名 #

sql
-- 命名约束便于管理
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    email TEXT,
    name TEXT,
    
    -- 命名唯一约束
    CONSTRAINT uk_users_email UNIQUE (email),
    
    -- 命名检查约束
    CONSTRAINT chk_users_name CHECK (length(name) >= 2),
    
    -- 命名主键
    CONSTRAINT pk_users PRIMARY KEY (id)
);

-- 查看约束
SELECT sql FROM sqlite_master WHERE type='table' AND name='users';

8.3 约束冲突处理 #

sql
-- ON CONFLICT 子句
-- 用于处理约束冲突

-- INSERT OR REPLACE
INSERT OR REPLACE INTO users (id, name) VALUES (1, 'Alice');

-- INSERT OR IGNORE
INSERT OR IGNORE INTO users (id, name) VALUES (1, 'Alice');

-- INSERT OR ABORT(默认)
INSERT OR ABORT INTO users (id, name) VALUES (1, 'Alice');

-- INSERT OR FAIL
INSERT OR FAIL INTO users (id, name) VALUES (1, 'Alice');

-- INSERT OR ROLLBACK
INSERT OR ROLLBACK INTO users (id, name) VALUES (1, 'Alice');

-- 在表定义中指定冲突处理
CREATE TABLE users (
    id INTEGER PRIMARY KEY ON CONFLICT REPLACE,
    email TEXT UNIQUE ON CONFLICT IGNORE
);

九、表设计最佳实践 #

9.1 主键设计 #

sql
-- 推荐:使用 INTEGER PRIMARY KEY
CREATE TABLE users (
    id INTEGER PRIMARY KEY,  -- 自增,高效
    name TEXT
);

-- 或明确使用 AUTOINCREMENT
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,  -- 保证ID不重用
    name TEXT
);

-- 不推荐:使用 TEXT 或复合主键作为主键
-- 除非有特殊需求
CREATE TABLE users (
    uuid TEXT PRIMARY KEY,  -- 较大,效率较低
    name TEXT
);

9.2 索引设计 #

sql
-- 为常用查询条件创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);

-- 复合索引顺序
-- 将最常用的列放在前面
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);

-- 覆盖索引
-- 包含查询所需的所有列
CREATE INDEX idx_users_active ON users(status, name, email);

9.3 数据类型选择 #

sql
-- 整数类型
id INTEGER PRIMARY KEY
age INTEGER
count INTEGER

-- 文本类型
name TEXT
email TEXT
description TEXT

-- 浮点数
price REAL
rate REAL

-- 布尔值
is_active INTEGER DEFAULT 1  -- 0=false, 1=true

-- 日期时间
created_at TEXT DEFAULT CURRENT_TIMESTAMP

十、总结 #

创建表语法 #

sql
CREATE TABLE [IF NOT EXISTS] [TEMP] table_name (
    column_definition,
    ...,
    table_constraints
) [WITHOUT ROWID];

修改表操作 #

操作 语法
重命名表 ALTER TABLE t1 RENAME TO t2
添加列 ALTER TABLE t1 ADD COLUMN col definition
重命名列 ALTER TABLE t1 RENAME COLUMN c1 TO c2
删除列 ALTER TABLE t1 DROP COLUMN col

约束类型 #

约束 列级 表级
PRIMARY KEY
FOREIGN KEY -
UNIQUE
NOT NULL -
CHECK
DEFAULT -

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

最后更新:2026-03-27