INSERT VALUES 是什么
INSERT … VALUES 按列清单插入一行或多行数据。显式写出列名比依赖表的列顺序更抗结构变更:加列、调整列顺序都不会让插入错位。多行 VALUES 一次写入比循环单行插入少掉大量网络往返与事务开销,是批量导入的首选写法。自增主键列应留空或写 NULL 交给数据库生成,有默认值的列可以省略。批量规模要控制,单条语句过大会触碰 max_allowed_packet 之类的上限,失败时也会整批回滚。
基本信息
| 基本语法 | INSERT INTO 表 (列1, 列2) VALUES (值1, 值2) |
|---|---|
| 多行插入 | VALUES (…), (…), (…) 一条语句写多行 |
| 列清单 | 建议显式写出;省略时按表定义顺序,结构变化容易错位 |
| 自增列 | 留空或写 NULL 由数据库生成,显式写值会推进自增计数器 |
| 默认值 | 省略该列或用 DEFAULT 关键字,让表默认值生效 |
| 平台差异 | 冲突处理写法不同:MySQL 用 IGNORE 或 ON DUPLICATE KEY,PostgreSQL 用 ON CONFLICT |
典型使用场景
- 初始化测试数据:一条语句插入多行,脚本简洁易读
- 批量导入:从 CSV 或上游系统导数据入库
- 不重复插入:MySQL 用 INSERT IGNORE,PostgreSQL 用 ON CONFLICT DO NOTHING
- 存在则更新:改用 upsert 语法,一条语句完成判断
- 小批量数据迁移:字段对齐后直接写入目标表
- 初始化默认行:新用户注册时补一条配置记录
示例
示例
INSERT INTO users (name, email, city, status) # 显式列清单
VALUES ('Li Lei', 'li@example.com', 'Beijing', 1), # 第一行
('Han Mei', 'han@example.com', 'Shanghai', 1), # 第二行
('Wang Wu', NULL, 'Chengdu', 0); # NULL 要求该列允许为空
-- 只写部分列,其余走表默认值
INSERT INTO users (name, created_at) VALUES ('Zhao Liu', NOW());冲突处理与分批
冲突处理与分批
-- MySQL:遇到重复键跳过
INSERT IGNORE INTO users (name, email) VALUES ('A', 'a@x.com');
-- PostgreSQL:无重复时才插入
INSERT INTO users (name, email) VALUES ('A', 'a@x.com')
ON CONFLICT (email) DO NOTHING;
-- 大批量插入改成分批执行,每批 500 到 1000 行
INSERT INTO t (a, b) VALUES (1, 2), (3, 4); # 循环分批重复执行
-- 从查询结果插入,注意列数与类型对齐
INSERT INTO archive_orders (id, amount) SELECT id, amount FROM orders WHERE created_at < '2023-01-01';插入写法与语义
| 写法 | 语义 | 注意 |
|---|---|---|
| INSERT INTO … VALUES | 插入新行 | 唯一键冲突直接报错 |
| INSERT IGNORE | 冲突跳过 | MySQL 专有,也会忽略其它错误 |
| ON CONFLICT DO NOTHING | 冲突跳过 | PostgreSQL 的标准写法 |
| ON DUPLICATE KEY UPDATE | 冲突时更新 | MySQL 专有,冲突也会消耗自增值 |
| INSERT … SELECT | 从查询结果插入 | 列数与顺序必须对齐 |
| REPLACE INTO | 先删后插 | MySQL 专有,会触发删除并丢默认值 |
多行 VALUES 比多条单行 INSERT 快得多,原因是解析一次、网络往返一次、事务提交一次;但也别把几十万行塞进一条语句,分批更稳妥。
省略列清单时插入依赖表的列顺序,后续加列或调整顺序可能让数据写进错误的列,生产脚本一律显式列出列名。
MySQL 的 INSERT IGNORE 会把所有错误降级为告警,不只是重复键,数据被截断或类型转换失败也会被静默跳过,导入后要核对行数。
插入后取回自增主键的方式不同:MySQL 用 LAST_INSERT_ID()(应用层通常是接口返回),PostgreSQL 用 INSERT … RETURNING id。
插入实践要点
- 批量插入控制规模:每批 500 到 1000 行,兼顾速度与事务大小
- 大表导入可以延后重建二级索引,导完再统一建,避免逐行维护索引
- 插入前确认表约束:非空、唯一、外键任一不满足都会整行失败
- 取回自增主键用 RETURNING 或接口返回值,不要用 SELECT MAX(id) 猜
- 初始化脚本要可重复执行:用 upsert 或先清理再插入,避免重复导入产生脏数据
插入前先定主键策略:自增、UUID、业务编号各有取舍,主键类型与生成方式一旦上线,后续改造成本很高。
插入的列上若有外键约束,父表记录必须先存在,否则整行插入失败;批量导入时要按表之间的依赖顺序安排。