mysql中INSERT INTO语句插入数据的常见方式

MySQL批量插入有四种方式:1. INSERT INTO VALUES适用于小量已知数据;2. INSERT INTO SELECT用于跨表导入;3. INSERT IGNORE/ON DUPLICATE KEY UPDATE处理重复键;4. LOAD DATA INFILE最快,适合百万级本地文件导入。

mysql中insert into语句插入数据的常见方式

INSERT INTO VALUES 一次性插入单行或多行数据

最基础的写法,适合已知全部字段值、数据量不大的场景。注意字段顺序必须和表定义一致,或显式指定列名避免出错。

常见错误:列数和值数量不匹配,报错 Column count doesn't match value count;插入 NULL 到 NOT NULL 字段导致失败。

  • 推荐始终显式列出列名,尤其当表结构后续可能增加字段时
  • 多行插入比多次单行 INSERT 更快,MySQL 会合并为一个事务批次处理
  • 单次插入行数不宜过多(如超过 1000 行),否则可能触发 max_allowed_packet 限制
INSERT INTO users (name, email, created_at) 
VALUES 
('Alice', 'alice@example.com', NOW()),
('Bob', 'bob@example.com', NOW()),
('Charlie', 'charlie@example.com', NOW());

INSERT INTO SELECT 从其他表批量导入数据

适用于迁移、归档、统计汇总等场景,本质是把 SELECT 查询结果作为数据源插入目标表。

关键点:目标表字段类型、长度、约束需兼容查询结果;若目标表有自增主键,SELECT 中通常不提供该列(除非显式设为 NULL 或具体值并关闭 sql_mode=NO_AUTO_VALUE_ON_ZERO)。

  • 不会触发源表的触发器,但会触发目标表的 INSERT 触发器
  • 执行期间会对源表加读锁(InnoDB 下通常是快照读,影响较小;MyISAM 则可能阻塞写)
  • 可配合 WHEREJOIN聚合函数使用,但要注意目标列数与 SELECT 列数严格一致
INSERT INTO user_archive (id, name, email, archived_at)
SELECT id, name, email, NOW() 
FROM users 
WHERE last_login < DATE_SUB(NOW(), INTERVAL 2 YEAR);

INSERT IGNORE 和 ON DUPLICATE KEY UPDATE 处理重复键冲突

当插入数据可能违反 UNIQUE 约束或主键时,两者策略不同:INSERT IGNORE 直接跳过冲突行;ON DUPLICATE KEY UPDATE 则更新已有记录。

降迹灵AI

降迹灵AI

用户口碑TOP级的降AIGC率、降重平台

下载

容易忽略的坑:IGNORE 会静默吞掉所有警告(包括非主键冲突的其他问题),不利于排查;UPDATE 子句中不能引用被更新行的旧值做计算(如 count = count + 1 是合法的,但 updated_at = old.updated_at 不行)。

  • INSERT IGNORE 返回的 affected_rows 为 0 表示跳过,1 表示插入成功,2 表示“本应插入但因重复被忽略”(仅部分 MySQL 版本)
  • ON DUPLICATE KEY UPDATE 只响应定义了 UNIQUEPRIMARY KEY 的列冲突,普通索引无效
  • 若表有多个唯一键,任一触发都会执行 UPDATE,需确认业务逻辑是否预期如此
INSERT INTO stats (date, page, views) 
VALUES ('2024-06-01', '/home', 120)
ON DUPLICATE KEY UPDATE views = views + 1;

使用 LOAD DATA INFILE 批量导入大文件数据

这是 MySQL 原生最快的批量插入方式,适合从 CSV、TSV 等文本文件导入数十万行以上数据。比拼接 SQL 插入快 20 倍以上。

权限和路径限制最多:需要 FILE 权限;文件必须位于数据库服务器本地(不是客户端);默认只允许 /var/lib/mysql-files/ 等白名单目录(由 secure_file_priv 控制)。

  • 字段分隔符、行结束符、转义字符需与文件格式严格匹配,否则解析错位
  • 建议先用 SHOW VARIABLES LIKE 'secure_file_priv' 查看允许路径
  • 导入前确保目标表无外键约束或临时禁用(SET FOREIGN_KEY_CHECKS = 0),否则速度骤降
LOAD DATA INFILE '/var/lib/mysql-files/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '/n'
IGNORE 1 ROWS
(name, email, @dummy_created_at)
SET created_at = STR_TO_DATE(@dummy_created_at, '%Y-%m-%d %H:%i:%s');

实际用哪一种,取决于数据来源、规模、是否需去重、以及你有没有服务器文件访问权限。小量手工插入用 VALUES,跨表搬运用 SELECT,高频写入带幂等性要求用 ON DUPLICATE KEY UPDATE,而百万级离线导入几乎只能靠 LOAD DATA INFILE —— 其他方式在性能和稳定性上都撑不住。

https://www.php.cn/faq/1963761.html

发表回复

Your email address will not be published. Required fields are marked *