INSERT ... VALUES 用于手动插入静态值,适用于明确具体值且不依赖现有数据的场景;INSERT ... SELECT 用于从已有表动态查询并插入数据,适用于数据迁移、归档等需基于条件筛选的场景。
INSERT ... VALUES 和 INSERT ... SELECT 是 MySQL 中两类根本不同的插入方式,不是写法风格差异,而是数据来源和语义完全不同:前者是「手动提供静态值」,后者是「从已有表动态查出数据再插入」。
INSERT ... VALUES?当你明确知道要插入哪些具体值(比如注册一个新用户、录入一条订单),且这些值不依赖数据库中已有的行时,就用它。
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');INSERT INTO users (name, email) VALUES
('Bob', 'bob@example.com'),
('Charlie', 'c@example.com'),
('Diana', 'd@example.com');VALUES 关键字 —— 写
成 INSERT INTO t VALUES (1) SELECT ... 会直接报错 ERROR 1064
'2025-12-30'
INSERT ... SELECT?当你想把「另一个表里符合条件的数据」搬过来,或者做数据归档、迁移、去重、补全等操作时,只能靠它。
INSERT INTO archive_orders (order_id, amount, created_at) SELECT id, total, created FROM orders WHERE status = 'shipped';
INSERT INTO logs (event, source, created_at) SELECT 'user_login', 'web', NOW() FROM users WHERE last_login > '2025-12-01';
VALUES —— 常见错误:INSERT INTO t(col) VALUES (SELECT ...) 语法非法ON DUPLICATE KEY UPDATE 或改用 REPLACE INTO)两者对缺失字段的处理逻辑不同,这点极易引发静默错误。
INSERT ... VALUES:没写的列,若允许 NULL 就填 NULL;若有 DEFAULT 就用默认值;若既不允许 NULL 又没默认值,直接报错 ERROR 1364
INSERT ... SELECT:SELECT 返回的列数必须等于 INSERT 指定的列数。少一列?报错;多一列?也报错。不会自动补 NULL 或默认值,除非你在 SELECT 里显式写 NULL AS col_name
INSERT INTO t VALUES (...),一旦后续加了新字段或调整顺序,语句就可能插错列甚至失败没有“哪个更快”的绝对答案,关键看场景。
VALUES 多行写法最简洁高效SELECT 方式天然批处理,还支持 WHERE/JOIN/GROUP BY 过滤聚合VALUES?可以用程序生成 SQL,但注意单条语句别超 max_allowed_packet(默认 64MB)LOW_PRIORITY 或分批次执行,避免锁表太久影响查询MySQL 不强制你选哪一种,但混淆它们的语义(比如误以为 VALUES 后能跟子查询)会导致语法错误或数据错位——这种错往往在上线后才暴露,且难以回溯。