Skip to content

插入(INSERT) ​

定义 ​

INSERT 向表中追加一行或多行数据。可指定列清单与值列表对应,省略列时使用 DEFAULT 或 NULL;支持 INSERT ... SELECT 从查询结果批量插入,以及 DEFAULT VALUES 插入一行且各列均取默认值。

概念要点 ​

  • 列清单可选:省略时须为全部列提供值,且顺序与表定义一致(含隐藏列时需注意)。
  • DEFAULT:列有 DEFAULT 且未出现在 INSERT 清单中则使用默认值;无 DEFAULT 的可空列则为 NULL。
  • INTEGER PRIMARY KEY 省略:不指定 id 时自动分配 rowid(见 建表)。
  • 多行 INSERT:一条语句多个 VALUES 元组,减少往返。
  • INSERT SELECT:目标列与 SELECT 列数、类型应匹配(SQLite 动态类型较宽松)。
  • RETURNING(3.35+):插入后返回新行字段(与 更新与删除 相同子句)。
  • 冲突处理:违反 UNIQUE/PK 时报错;需静默或更新时用 替换与 UPSERT。

语法 / 清单表 ​

形式语法用途
指定列INSERT INTO t (a,b) VALUES (1,'x')常用
全列INSERT INTO t VALUES (...)列顺序须与表一致
多行INSERT INTO t (a) VALUES (1), (2), (3)批量
查询插入INSERT INTO t (a,b) SELECT x,y FROM s拷贝/迁移
默认行INSERT INTO t DEFAULT VALUES各列 DEFAULT/NULL
返回值INSERT INTO t (...) VALUES (...) RETURNING id取新主键

INSERT 与约束交互 ​

情况结果
NOT NULL 列未提供且无 DEFAULT错误
UNIQUE/PK 重复错误(除非 UPSERT)
FK 引用不存在错误(需 foreign_keys=ON)
CHECK 不满足错误
GENERATED 列不要出现在 INSERT 列清单

示例 ​

基本插入与 DEFAULT ​

sql
PRAGMA foreign_keys = ON;

CREATE TABLE tasks (
  id          INTEGER PRIMARY KEY,
  title       TEXT    NOT NULL,
  status      TEXT    NOT NULL DEFAULT 'todo',
  priority    INTEGER DEFAULT 0,
  created_at  TEXT    DEFAULT (datetime('now'))
);

-- 只写必填列,其余用 DEFAULT
INSERT INTO tasks (title) VALUES ('学习 SQLite');
INSERT INTO tasks (title, status) VALUES ('写文档', 'doing');

-- 一行全用默认值(id 自动分配,title 无 DEFAULT 会失败 — 此例 title NOT NULL 不可用 DEFAULT VALUES)
-- INSERT INTO tasks DEFAULT VALUES;  -- 会报错:title NOT NULL

多行 INSERT ​

sql
INSERT INTO tasks (title, priority) VALUES
  ('任务 A', 1),
  ('任务 B', 2),
  ('任务 C', 3);
-- 一次语句插入三行,比三条 INSERT 更高效

INSERT SELECT 与 RETURNING ​

sql
CREATE TABLE tasks_archive AS SELECT * FROM tasks WHERE 0;  -- 空表同结构

INSERT INTO tasks_archive (id, title, status, priority, created_at)
SELECT id, title, status, priority, created_at
FROM tasks
WHERE status = 'done';  -- 把已完成任务归档

-- 插入并返回新 rowid
INSERT INTO tasks (title) VALUES ('新任务')
RETURNING id, created_at;

易错点与交叉引用 ​

问题说明
VALUES 列数不匹配与列清单或全表列数不一致则报错
省略列但顺序错全列 INSERT 依赖表定义顺序,ALTER ADD 后顺序变化
忘记开外键插入非法 user_id 可能不被拒绝
对 GENERATED 列 INSERT应省略,由表达式计算
大事务一次插百万行注意 journal 与内存;可分批 + 事务
与 UPSERT 混淆普通 INSERT 冲突即失败;要「有则更新」见 替换与 UPSERT
字符串引号文本值用单引号 '...';双引号是标识符引号

批量插入与事务 ​

大量写入时宜包在事务中,减少 fsync 次数:

sql
BEGIN;
INSERT INTO logs (msg) VALUES ('line 1');
INSERT INTO logs (msg) VALUES ('line 2');
-- ... 或单条多行 INSERT
COMMIT;

相关章节:建表 · 约束 · 更新与删除 · 替换与 UPSERT · SELECT

SQLite 官方参考 ​