INSERT INTO 的基本写法(必须指定字段)
最稳妥、最推荐的写法是显式列出目标字段,避免因表结构变更导致插入失败或数据错位:
INSERT INTO <code>users</code> (<code>id</code>, <code>name</code>, <code>email</code>) VALUES (1, 'Alice', 'alice@example.com');
不写字段名直接用
INSERT INTO users VALUES (...)仅在明确知道所有列顺序且表结构长期稳定时可用,但极易出错——比如后续加了
created_at默认字段,就可能把邮箱值插进时间字段。
INSERT ... SET 适合单行且字段少的场景
当只插入一行、字段不多,又不想写括号嵌套时,
SET语法更直观,可读性高:
INSERT INTO <code>users</code> SET <code>name</code> = 'Bob', <code>email</code> = 'bob@example.com', <code>status</code> = 'active';不能用于多行插入 不支持
VALUES后的表达式简写(如
NOW()可用,但不能省略字段名) 某些 ORM 或自动化工具不识别该语法,兼容性略低
批量插入用 VALUES 多元组,别用多条单行语句
插入 100 行数据时,用一条语句带多个
VALUES元组,比发 100 次
INSERT快数倍:
INSERT INTO <code>logs</code> (<code>level</code>, <code>message</code>, <code>ts</code>) VALUES
('ERROR', 'Connection timeout', NOW()),
('WARN', 'Disk usage >90%', NOW()),
('INFO', 'User login success', NOW());
单条语句最大长度受 max_allowed_packet限制,默认通常 4MB,超限会报错
Packets larger than max_allowed_packet are not allowed事务中批量插入能减少日志刷盘次数,但单次太大可能锁表时间变长 避免在循环里拼接 SQL 字符串插入,有注入风险;应使用参数化查询或批量执行接口
ON DUPLICATE KEY UPDATE 不是 REPLACE INTO
遇到唯一键冲突时,想更新而非报错,优先用
ON DUPLICATE KEY UPDATE:
INSERT INTO <code>stats</code> (<code>date</code>, <code>page_views</code>) VALUES ('2024-06-01', 100)
ON DUPLICATE KEY UPDATE <code>page_views</code> = <code>page_views</code> + 1;
REPLACE INTO实际是「删+插」,会触发 DELETE 和 INSERT 两轮触发器,还可能导致自增 ID 跳变
ON DUPLICATE KEY UPDATE只更新,不改变主键,也不影响自增值 注意:只响应定义为
PRIMARY KEY或
UNIQUE的索引冲突,普通索引无效 MySQL 的
INSERT看似简单,真正容易翻车的是隐式字段顺序、批量大小失控、以及对冲突处理机制的误用。尤其是线上环境,别图省事省字段名,也别把
REPLACE INTO当万能更新方案。
