标准写法是单条INSERT语句后接多组用英文逗号分隔的圆括号VALUES,字段顺序与数量须严格一致,各主流数据库均支持;需注意类型匹配、长度限制(建议≤1000行)及避免隐式转换。

可以直接用 VALUES 构造器在一条 INSERT 语句里插入多行,无需循环或多次执行,但必须注意括号嵌套、类型对齐和数据库兼容性。
VALUES 后面跟多个元组的写法
标准 SQL(PostgreSQL、SQL Server、SQLite 支持)允许在 VALUES 后连续列出多个用逗号分隔的括号元组:
INSERT INTO users (name, age) VALUES ('Alice', 25), ('Bob', 30), ('Charlie', 35);
每个括号内字段顺序、数量、类型必须与 INSERT 子句中列定义严格一致。常见错误是漏掉括号、多加逗号、或某一行字段数不匹配——这时多数数据库会报类似 ERROR: column "xxx" is of type integer but expression is of type text 或 too few columns specified 的错误。
- MySQL 8.0.19+ 才支持这种标准写法;老版本只能靠
INSERT ... SELECT UNION ALL模拟 - Oracle 不支持裸
VALUES多行,得包装成SELECT ... FROM DUAL或用INSERT ALL - 字段名列表不能省略(除非插全部列),否则各元组顺序无法对齐
和 INSERT ... SELECT UNION ALL 对比
有些旧环境仍用 SELECT ... UNION ALL 拼多行,例如:
INSERT INTO users (name, age) SELECT 'Alice', 25 UNION ALL SELECT 'Bob', 30 UNION ALL SELECT 'Charlie', 35;
这种写法兼容性更广(MySQL 5.7、早期 PostgreSQL 都能跑),但性能略差:每 SELECT 是独立子查询,优化器难统一处理;而原生 VALUES 多元组会被当做一个常量集合,解析和执行更快。
-
VALUES方式在 PostgreSQL 中可被RETURNING直接返回所有新生成的id,UNION ALL方式做不到 - 如果某行插入失败(如违反唯一约束),
VALUES整条语句回滚;UNION ALL方式也一样,不是“部分成功” - 别在
VALUES里混用子查询(如('Alice', (SELECT MAX(age) FROM users))),部分数据库不支持
带 DEFAULT 或 NULL 值的注意事项
多行 VALUES 中,DEFAULT 和 NULL 必须显式写出,不能留空:
INSERT INTO logs (msg, level, created_at) VALUES ('start', 'INFO', DEFAULT), ('fail', 'ERROR', '2024-01-01 10:00:00');
如果某列允许 NULL 且你想插空值,必须写 NULL,不能省略字段或写空字符串代替。
- 省略字段会导致该行字段数不足,直接报错
-
''(空字符串)和NULL语义不同,尤其在NOT NULL约束或索引行为上 - PostgreSQL 支持
DEFAULT关键字,MySQL 要求列本身有默认值定义才能用,否则报错
真正容易被忽略的是字段类型的隐式转换边界——比如 VALUES ('123', 45) 插入到 (VARCHAR(10), NUMERIC(5,2)) 表时,第二列会自动转成 45.00,但若写成 ('123', '45') 就可能触发类型不匹配错误。动手前最好先 DESCRIBE table_name 或查 information_schema 确认目标列类型。

















