
INSERT INTO ... VALUES 多行语法怎么写才不报错
MySQL 原生支持单条 INSERT 语句插入多行,但括号嵌套和逗号分隔稍有不慎就触发 SQL syntax error 或被截断。关键不是“能不能”,而是“括号配对”和“字段数一致”。
- 每组值必须用
(...)包裹,组之间用英文逗号分隔,末尾不能有逗号 - 所有行的字段数量必须严格等于
INSERT INTO table (col1, col2)中声明的列数 - 字符串值必须用单引号包裹,
NULL不加引号,数字直接写 - 示例:
INSERT INTO users (name, age) VALUES ('Alice', 25), ('Bob', 30), ('Charlie', 28);
LOAD DATA INFILE 导入 CSV 时中文乱码或字段错位
LOAD DATA INFILE 是批量导入最快的方式,但默认字符集是 latin1,且字段分隔符、行结束符不显式指定就容易错位。
- 务必加
CHARACTER SET utf8mb4,尤其含 emoji 或中文时 - 用
FIELDS TERMINATED BY ','显式声明分隔符,避免 CSV 中带逗号的字段被切碎 - 用
LINES TERMINATED BY '\n'(Linux)或'\r\n'(Windows),否则最后一行可能丢数据 - 文件路径必须是 MySQL 服务端可读路径(不是你本地桌面),常见错误:
ERROR 13 (HY000): Can't get stat of '/path/to/file.csv'
INSERT IGNORE 和 ON DUPLICATE KEY UPDATE 的实际区别
两者都用于避免重复键冲突,但行为逻辑完全不同:一个“跳过”,一个“更新”。选错会导致数据静默丢失或覆盖错误字段。
-
INSERT IGNORE遇到主键/唯一键冲突时整行跳过,不报错也不插入,但也不会告诉你哪几行被忽略了 -
ON DUPLICATE KEY UPDATE要求明确写出更新字段,比如ON DUPLICATE KEY UPDATE status = VALUES(status), updated_at = NOW() -
VALUES(col)表示本次 INSERT 想插入的值,不是当前行原值;别误写成status = status - 如果表没定义主键或唯一索引,
ON DUPLICATE KEY UPDATE会直接报错ERROR 1062
批量插入性能差?别只怪数据量大
真正拖慢速度的往往不是数据本身,而是事务、索引、日志和客户端配置。
- 默认每条
INSERT都是独立事务,1000 行 = 1000 次磁盘刷写。用BEGIN; ... INSERT ... ; COMMIT;包裹可提速 5–10 倍 - 插入前临时禁用非必要索引:
ALTER TABLE tbl DISABLE KEYS;,插完再ENABLE KEYS;(仅 MyISAM 有效;InnoDB 不适用) - InnoDB 下调大
innodb_log_file_size和innodb_buffer_pool_size对大批量插入帮助明显 - PHP 的
mysqli或 Python 的pymysql默认开启 autocommit,记得关掉:conn.autocommit(False)
最常被忽略的是:LOAD DATA INFILE 虽快,但需要文件在数据库服务器上;而多行 INSERT 看似简单,一旦单条语句超长(比如 10 万行拼一起),会触发 max_allowed_packet 限制,默认才 4MB。拆成每 1000 行一批,比硬扛更稳。


















