如何用 VALUES 子句实现多行插入的批量写法

26次阅读

支持,VALUES子句支持多行插入,是sql:1992以上标准的简洁高效批量插入方式,语法为VALUES (‘a’,1), (‘b’,2),需字段数一致、类型兼容,且整条语句失败无容错。

如何用 VALUES 子句实现多行插入的批量写法

VALUES 子句支持多行插入吗?

支持,而且这是标准 SQL 中最简洁、最高效的批量插入方式之一。只要数据库支持 SQL:1992 以上标准(postgresql、SQL Server、mysql 8.0+、sqlite 3.7.11+ 都满足),VALUES 后面直接跟多组括号即可,无需拼接多个 INSERT 语句或依赖扩展语法。

VALUES 多行写法的正确语法结构

核心是把每行数据用一对圆括号包裹,逗号分隔,整体作为 VALUES 的参数。注意括号层级和逗号位置,少一个括号或错放逗号会直接报语法错误。

  • INSERT intO users (name, age) VALUES ('Alice', 25), ('Bob', 30), ('Charlie', 35);
  • 字段列表必须与每组值一一对应;类型要兼容,比如不能把字符串塞进 INT
  • 所有行共用同一套字段定义,不能有的行写 2 列、有的写 3 列
  • MySQL 8.0.19+ 允许在 VALUES 中使用子查询,但多数场景下不建议混用,易读性下降且可能触发隐式转换

和 INSERT … select 或批量 INSERT 对比有什么坑?

VALUES 多行插入看起来简单,但实际部署时容易踩几个隐蔽点:

  • PostgreSQL 对单条语句长度有限制(默认 max_identifier_length=64,但真正卡住的是内存和解析器),插入上万行时可能报 out of memory 或超时,这时该切分成 100–500 行/批
  • SQLite 在 WAL 模式下对大 VALUES 语句性能尚可,但 autocommit 关闭时务必手动 BEGIN/COMMIT,否则每行都成独立事务
  • MySQL 的 max_allowed_packet 会拦截过长的 VALUES 语句,错误信息通常是 Packets larger than max_allowed_packet are not allowed,需调大该值或拆批
  • 如果某一行违反约束(如唯一键冲突),整条 INSERT 语句失败——不像 INSERT IGNOREON CONFLICT 那样有容错机制

什么时候不该硬上 VALUES 多行?

不是所有批量场景都适合裸写 VALUES。遇到这些情况,优先考虑替代方案:

  • 数据来自外部文件:用 copy(PostgreSQL)、LOAD DATA INFILE(MySQL)或客户端流式写入,比拼 SQL 字符串快一个数量级
  • 需要条件过滤或转换:改用 INSERT INTO ... SELECT ... FROM ... WHERE ...,逻辑更清晰且数据库可优化执行计划
  • 涉及序列/自增主键且需返回生成值:PostgreSQL 可用 RETURNING,但 MySQL 不支持多行 VALUES + LAST_INSERT_ID() 精确对应,容易串行错位
  • ORM 场景(如 SQLAlchemy、Django ORM):它们底层常把多行转成单行循环或使用 executemany,强行拼 VALUES 可能绕过连接池预编译,反而降低复用率

实际写的时候,别只盯着“能不能”,先看“值从哪来”“量有多大”“错了一行要不要继续”。VALUES 是利器,但刀刃朝哪,得看表结构、数据源和错误容忍度。

text=ZqhQzanResources