2.12 sql 数据插入(INSERT INTO)

2.12 数据插入(INSERT INTO)

我刚入行时,以为数据分析师只需要SELECT查数据就够了。直到有一次,运营同事拿着一份Excel表格找到我:"这是618大促的临时订单数据,你帮我把这些数据导入数据库,我要做分析。"我愣住了------我只会查,不会插。后来我硬着头皮学了INSERT INTO,才发现原来往数据库里写数据并不难。

在电商数据分析工作中,你可能会遇到这些场景:

  • 运营从第三方平台导出了一批线下订单,需要导入数据库与线上订单合并分析。

  • 大促期间,需要将实时订单数据写入临时表,供监控看板使用。

  • 数据清洗后,将结果写入新表,供后续报表使用。

  • 定期将历史数据归档到备份表。

这一章我会带你彻底搞懂INSERT INTO语句的所有用法:全字段插入、指定字段插入、单行插入、批量插入,甚至将查询结果直接插入另一张表。学完之后,你不仅能查数据,还能自己建表、导数据,成为一个更全能的分析师。

学习前准备:

  • 已完成MySQL安装(参考系列前几章)

  • 已安装DBeaver或Navicat

  • 准备一个练习数据库,比如insert_demo

学习前环境准备(快速回顾)

如果你已经完成了前面的教程,可以跳过本节。否则按以下步骤快速搭建练习环境。

步骤1:确保MySQL服务已启动。

步骤2:创建练习数据库。

sql 复制代码
CREATE DATABASE insert_demo
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE insert_demo;

步骤3:创建一张订单表作为演示。

sql 复制代码
CREATE TABLE orders (
    order_id VARCHAR(50) PRIMARY KEY COMMENT '订单号',
    user_id INT NOT NULL COMMENT '用户ID',
    amount DECIMAL(10,2) NOT NULL COMMENT '金额',
    order_status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1待支付,2已支付,3已取消,4已完成',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间'
);

INSERT INTO基础认知

INSERT INTO是SQL中用于向表中添加新行的语句。它是DML(数据操纵语言)的一部分。数据分析师虽然以查询为主,但以下情况必须用到插入:

  • 将外部数据(CSV、Excel)导入数据库暂存。

  • 创建临时表用于复杂分析。

  • 数据清洗后将结果写入新表。

  • 将历史数据归档。

基本语法格式

sql 复制代码
INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);

我的踩坑经历 :第一次用INSERT INTO时,我把列名写错了顺序,导致金额插到了用户ID字段里,变成了一堆奇怪的数字。从那以后,我养成习惯:指定列名时,顺序和数据类型一定要与VALUES一一对应

全字段插入与指定字段插入

4.1 全字段插入(省略列名)

如果为表中所有列 提供值,可以省略列名,直接写VALUES。值的顺序必须与表定义时的列顺序完全一致。

sql 复制代码
INSERT INTO orders VALUES ('ORD001', 1001, 299.00, 2, '2025-06-01 10:00:00');

分步操作

  1. 确认表结构:DESC orders; 查看列顺序。

  2. 按顺序提供值:字符串用单引号,数字直接写,日期时间用'YYYY-MM-DD HH:MM:SS'

  3. 执行语句,成功插入一行。

预期结果Query OK, 1 row affected

注意 :如果表有自增列或默认值列,全字段插入时也需要显式提供值(可以用DEFAULT关键字)。

4.2 指定字段插入(推荐)

只给部分列赋值,其他列使用默认值或允许NULL。必须明确列出要插入的列名。

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status)
VALUES ('ORD002', 1002, 189.00, 1);

这里create_time列有默认值CURRENT_TIMESTAMP,会自动填充。

分步操作

  1. INSERT INTO orders (列名列表)

  2. VALUES中值数量与列名列表数量一致。

  3. 执行,查看结果:SELECT * FROM orders;

预期结果 :新增一行,create_time自动为当前时间。

4.3 电商场景实操

运营需要将线下手工订单录入系统,只有订单号、用户ID和金额,状态默认为"已支付"(状态码2)。

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status)
VALUES ('OFFLINE001', 8888, 599.00, 2);

实操避坑提醒 :全字段插入虽然省事,但表结构可能变化(如新增字段),导致语句报错或数据错位。生产环境推荐使用指定字段插入,明确列出列名,可读性更好,也更安全。

单行插入与批量插入

5.1 单行插入

一次只插入一行数据,就是前面讲的基本语法。

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status)
VALUES ('ORD003', 1003, 399.00, 2);

5.2 批量插入(一次插入多行)

VALUES后用逗号分隔多组括号,每组代表一行。效率远高于逐条插入,尤其适合大数据量导入。

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status) VALUES
('ORD004', 1004, 129.00, 2),
('ORD005', 1005, 499.00, 1),
('ORD006', 1006, 59.00, 4);

分步操作

  1. 准备多行数据,每组值用括号包围,逗号分隔。

  2. 执行语句,返回Query OK, 3 rows affected

  3. SELECT COUNT(*) FROM orders验证行数增加了3。

5.3 电商场景实操:大促订单数据批量入库

618大促期间,每小时会生成一批订单数据,需要批量插入到数据库的临时表中。

sql 复制代码
INSERT INTO orders_temp (order_id, user_id, amount, order_status, create_time) VALUES
('H202506011001', 1001, 299.00, 2, '2025-06-01 10:00:00'),
('H202506011002', 1002, 189.00, 2, '2025-06-01 10:01:00'),
('H202506011003', 1003, 599.00, 1, '2025-06-01 10:02:00');

注意 :批量插入的数据量建议一次不超过1000行,否则可能超过MySQL的max_allowed_packet限制。如果数据量很大,可以分批插入。

我的踩坑经历 :有一次我试图一次性插入10万行数据,结果MySQL报错Packet too large。后来我把数据分成每5000行一批,用脚本循环插入,顺利完成。批量插入虽快,也要注意单次数据包大小限制

查询结果插入(INSERT INTO ... SELECT)

6.1 核心定义

将一条SELECT查询的结果直接插入到目标表中。这是数据同步、备份、临时表创建的常用技巧。

语法

sql 复制代码
INSERT INTO 目标表 (列1, 列2, ...)
SELECT 列1, 列2, ...
FROM 源表
WHERE 条件;

6.2 电商场景实操:跨表同步

场景一:创建历史订单备份表

将2024年之前的订单移动到备份表。

sql 复制代码
-- 先创建结构相同的备份表
CREATE TABLE orders_archive LIKE orders;

-- 将旧数据插入备份表
INSERT INTO orders_archive
SELECT * FROM orders
WHERE create_time < '2024-01-01';

场景二:将退款订单单独存入退款表

假设有退款表refund_orders,结构与订单表类似,需要将已退款的订单同步过去。

sql 复制代码
-- 先创建退款表(简略版)
CREATE TABLE refund_orders (
    order_id VARCHAR(50) PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    refund_time DATETIME
);

-- 从订单表查询已取消的订单(假设取消即退款)
INSERT INTO refund_orders (order_id, user_id, amount, refund_time)
SELECT order_id, user_id, amount, NOW()
FROM orders
WHERE order_status = 3;

分步操作

  1. 确认源表有需要的数据。

  2. 确认目标表已存在,且列数据类型兼容。

  3. 执行INSERT INTO ... SELECT

  4. 验证目标表中的行数。

预期结果:所有符合条件的订单被复制到退款表。

6.3 避坑提醒

  • 目标表必须提前存在,不会自动创建。

  • 列的数量、顺序、数据类型必须匹配。

  • 如果目标表有自增主键,SELECT中可以不包含该列,让数据库自动生成。

  • 如果目标表有唯一约束或主键,要避免插入重复数据。

我的踩坑经历 :有一次我用INSERT INTO ... SELECT同步数据,忘记目标表已经有一些数据了,结果插入了重复主键,语句报错。后来改用INSERT IGNOREON DUPLICATE KEY UPDATE来避免冲突。批量插入前最好先检查目标表是否为空,或使用去重逻辑

综合实操案例:618大促订单数据批量入库与退款数据同步

7.1 案例背景

某服饰类目天猫店铺在618大促期间,需要完成以下任务:

  1. 将运营提供的线下订单CSV数据(模拟)批量插入到orders表。

  2. orders表中筛选出已退款的订单(状态=3),同步到refund_orders表。

7.2 准备工作

创建订单表(如果还没有)和退款表。

sql 复制代码
USE insert_demo;

CREATE TABLE IF NOT EXISTS orders (
    order_id VARCHAR(50) PRIMARY KEY,
    user_id INT NOT NULL,
    amount DECIMAL(10,2) NOT NULL,
    order_status TINYINT NOT NULL DEFAULT 1,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS refund_orders (
    refund_id INT PRIMARY KEY AUTO_INCREMENT,
    order_id VARCHAR(50) NOT NULL,
    user_id INT,
    amount DECIMAL(10,2),
    refund_time DATETIME,
    FOREIGN KEY (order_id) REFERENCES orders(order_id)
);

7.3 分步操作

步骤1:批量插入线下订单数据(模拟CSV导入)

假设有5条线下订单:

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status, create_time) VALUES
('OFF001', 2001, 399.00, 2, '2025-06-01 09:00:00'),
('OFF002', 2002, 259.00, 2, '2025-06-01 10:30:00'),
('OFF003', 2003, 699.00, 1, '2025-06-01 11:15:00'),
('OFF004', 2004, 129.00, 3, '2025-06-01 12:00:00'),
('OFF005', 2005, 499.00, 2, '2025-06-01 14:20:00');

步骤2:验证插入结果

sql 复制代码
SELECT COUNT(*) FROM orders;  -- 应该看到新增5行

步骤3:将已退款订单同步到退款表

sql 复制代码
INSERT INTO refund_orders (order_id, user_id, amount, refund_time)
SELECT order_id, user_id, amount, NOW()
FROM orders
WHERE order_status = 3;

步骤4:验证退款表数据

sql 复制代码
SELECT * FROM refund_orders;

预期结果 :退款表中有一条记录,对应OFF004订单。

步骤5:补充大促实时订单数据(批量插入)

模拟从实时系统导出的一批订单:

sql 复制代码
INSERT INTO orders (order_id, user_id, amount, order_status, create_time) VALUES
('ONLINE001', 3001, 199.00, 2, '2025-06-01 15:00:00'),
('ONLINE002', 3002, 899.00, 2, '2025-06-01 15:05:00'),
('ONLINE003', 3003, 49.00, 4, '2025-06-01 15:10:00');

7.4 结果验证与合规提示

  • 所有数据插入成功,无主键冲突。

  • 退款表正确同步了退款订单。

📌 电商数据合规提示 :在插入订单数据时,如果包含用户手机号、地址等敏感信息,必须先脱敏。本案例中订单表只有user_id(内部ID),不涉及个人敏感字段。生产环境中,INSERT INTO ... SELECT同步数据时,注意不要复制敏感字段。

本章踩坑清单与合规总结

8.1 新手常见踩坑

错误 原因 正确做法
全字段插入时顺序错误 没查看表结构 用指定字段插入,或DESC确认顺序
批量插入时一行写错导致全部失败 批量插入是原子操作 先少量测试,或用INSERT IGNORE
插入NULL到NOT NULL列 未提供值且无默认值 提供有效值或修改表结构
INSERT INTO ... SELECT目标表不存在 没提前建表 CREATE TABLE ... LIKE
插入重复主键 未检查唯一性 INSERT IGNOREON DUPLICATE KEY UPDATE

8.2 电商数据合规红线

  • 插入数据时不要包含明文敏感信息:如手机号、身份证号,必须加密或脱敏。

  • 批量导入外部数据需审批:来自第三方的数据可能存在合规风险(如爬虫数据),导入前需法务确认。

  • 数据备份:在插入大量数据前,先备份目标表,防止误操作导致数据丢失。

  • 使用事务 :如果插入操作涉及多表,应使用START TRANSACTIONCOMMIT,保证一致性。

结语

INSERT INTO是SQL中最基本的写入操作,但掌握它能让你的数据分析工作流更加完整。无论是导入外部数据、创建临时表,还是做数据归档,你都游刃有余。

有问题的评论区留言,我看到会回复。

相关推荐
薛定e的猫咪2 小时前
2026 年 4 月实测:OpenAI Codex 保姆级教程,从安装到 MCP、Skills 与多智能体协作
前端·数据库·人工智能
wgzrmlrm742 小时前
Django怎么优雅发送邮件_Python配置SMTP后端实现异步通知
jvm·数据库·python
014-code2 小时前
Redis 删除缓存失败怎么办?重试、死信、补偿的工程化方案
数据库·redis·缓存
I love studying!!!2 小时前
Web应用程序:用户账户
前端·数据库·sqlite
窝子面2 小时前
NestJs+MongoDB+Deepseek+Langchain实现ai聊天助手
javascript·数据库·人工智能·mongodb
zjshuster2 小时前
流程引擎(Process Engine)简介
java·数据库·servlet
leonkay2 小时前
关于.NET中的队列理解
数据库·性能优化·.net·个人开发·设计规范·队列
A__tao2 小时前
一键实现 SQL → ES Mapping 转换,支持自定义 `text` 为 `json` 转换
sql·elasticsearch·json
斌味代码2 小时前
Redis 分库分表实战:从垂直拆分到水平扩容完整记录
数据库·redis·bootstrap