mysql如何使用insert语句添加数据_mysql插入操作示例

来源:这里教程网 时间:2026-02-28 20:51:39 作者:

INSERT 语句的基本写法必须指定列名或按表结构顺序填值

MySQL 的

INSERT
不允许只写
VALUES
而不指明列,除非你**严格按建表时的字段顺序、且提供全部非 NULL 默认值字段**。更安全的做法是显式列出列名,避免因表结构变更(比如新增字段、调整顺序)导致插入失败或数据错位。

常见错误现象:

Column count doesn't match value count at row 1
Field 'xxx' doesn't have a default value

推荐写法:
INSERT INTO users (name, email, created_at) VALUES ('Alice', 'a@example.com', NOW());
危险写法(不推荐):
INSERT INTO users VALUES ('Alice', 'a@example.com', NOW());
—— 一旦表加了
id INT AUTO_INCREMENT PRIMARY KEY
在最前,这条就直接报错
如果某字段允许 NULL 或有 DEFAULT,可跳过它,但必须出现在列名列表中才“被跳过”;否则必须显式写
NULL
或对应值

批量插入用 VALUES 多组值比循环执行 INSERT 快得多

单条

INSERT
插入 100 行,用 100 次单独语句 vs 1 条带 100 组
VALUES
的语句,性能差距可达 10 倍以上——主要省去了网络往返和语句解析开销。

注意:MySQL 默认

max_allowed_packet
限制单条语句大小(通常 4MB),超限会报错
Packets larger than max_allowed_packet are not allowed

正确批量写法:
INSERT INTO logs (level, msg, time) VALUES ('WARN', 'disk full', '2024-01-01 12:00:00'), ('ERROR', 'db timeout', '2024-01-01 12:01:00');
每组
VALUES
之间用英文逗号分隔,不要加分号
单次插入行数建议控制在 1000 行以内,兼顾性能与内存/包大小安全

INSERT IGNORE 和 ON DUPLICATE KEY UPDATE 的行为差异很关键

遇到主键或唯一索引冲突时,

INSERT IGNORE
直接跳过整行,不报错也不更新;而
ON DUPLICATE KEY UPDATE
允许你指定冲突后更新哪些字段——这是实现“存在则更新、不存在则插入”(upsert)的核心手段。

容易踩的坑:

INSERT IGNORE
会静默吞掉其他错误(如字段类型不匹配),不利于调试;
REPLACE INTO
实际是先 DELETE 再 INSERT,会触发自增 ID 变化和外键级联动作,慎用。

忽略冲突:
INSERT IGNORE INTO users (id, name) VALUES (1, 'Bob');
冲突更新:
INSERT INTO users (id, name, updated_at) VALUES (1, 'Bob', NOW()) ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = NOW();
VALUES(name)
表示本次 INSERT 中该字段想设的值,不是当前行旧值

从 SELECT 结果插入数据要用 INSERT ... SELECT 语法

想把一张表的数据按条件复制到另一张表(或同一张表),不能用

VALUES
,必须用
INSERT ... SELECT
。它的字段数量、类型、顺序需与目标列兼容,否则报错。

注意:若 SELECT 返回空结果集,

INSERT ... SELECT
什么也不会插入,也不会报错——这点和普通 INSERT 不同,容易误以为执行失败。

基础用法:
INSERT INTO archive_logs (level, msg, time) SELECT level, msg, time FROM logs WHERE time 
支持 JOIN、子查询、常量、函数:
INSERT INTO reports (date, total) SELECT CURDATE(), COUNT(*) FROM orders WHERE status = 'paid';
目标列名可省略,但前提是 SELECT 字段数、顺序、类型完全匹配目标表定义(含自增、默认值等约束) 实际写 INSERT 时,最容易被忽略的是字符集和时区隐式转换问题:比如客户端连接用
utf8mb4
,但表字段是
latin1
,插入中文可能变问号;或者
NOW()
在不同时区会存成不同时间。这些不会报错,但数据已失真。

相关推荐