CRUD
前言
这篇笔记是我对数据库CRUD操作的整理,针对零基础入门者 和需要复习巩固的同学 设计。不同于简单的语法罗列,本文对每一个操作的底层逻辑、语法细节、使用场景、避坑要点 都做了详尽拆解,且每个知识点都搭配可直接复制运行的示例。
示例统一基于 MySQL 环境,采用 emp(员工表)和 dept(部门表)作为演示表,先明确表结构和测试数据,后续所有示例均围绕这两张表展开,确保学习时的连贯性。
目录
- 前置准备:演示表结构与测试数据
- 什么是CRUD
- [C - 数据插入(INSERT)](#C - 数据插入(INSERT))
- [3.1 单行插入(基础用法)](#3.1 单行插入(基础用法))
- [3.2 批量插入(高效用法)](#3.2 批量插入(高效用法))
- [3.3 插入查询结果(进阶用法)](#3.3 插入查询结果(进阶用法))
- [3.4 INSERT避坑核心要点](#3.4 INSERT避坑核心要点)
- [R - 数据查询(SELECT)](#R - 数据查询(SELECT))
- [4.1 基础查询:字段与表的核心关联](#4.1 基础查询:字段与表的核心关联)
- [4.2 条件查询:WHERE子句全解析](#4.2 条件查询:WHERE子句全解析)
- [4.3 排序查询:ORDER BY的精准使用](#4.3 排序查询:ORDER BY的精准使用)
- [4.4 限制结果:LIMIT分页与行限制](#4.4 限制结果:LIMIT分页与行限制)
- [4.5 分组查询:GROUP BY与聚合函数](#4.5 分组查询:GROUP BY与聚合函数)
- [4.6 分组过滤:HAVING与WHERE的区别](#4.6 分组过滤:HAVING与WHERE的区别)
- [4.7 多表联查:JOIN的三种核心类型](#4.7 多表联查:JOIN的三种核心类型)
- [U - 数据修改(UPDATE)](#U - 数据修改(UPDATE))
- [5.1 单表修改(基础用法)](#5.1 单表修改(基础用法))
- [5.2 多字段同时修改](#5.2 多字段同时修改)
- [5.3 结合WHERE的精准修改(核心)](#5.3 结合WHERE的精准修改(核心))
- [5.4 结合聚合函数的批量修改(进阶)](#5.4 结合聚合函数的批量修改(进阶))
- [5.5 UPDATE避坑核心要点](#5.5 UPDATE避坑核心要点)
- [D - 数据删除(DELETE)](#D - 数据删除(DELETE))
- [6.1 单条记录删除(基础用法)](#6.1 单条记录删除(基础用法))
- [6.2 批量记录删除](#6.2 批量记录删除)
- [6.3 多表关联删除(进阶)](#6.3 多表关联删除(进阶))
- [6.4 DELETE与TRUNCATE的区别(关键)](#6.4 DELETE与TRUNCATE的区别(关键))
- [6.5 DELETE避坑核心要点](#6.5 DELETE避坑核心要点)
- CRUD综合实战案例
- 核心知识点速记表
前置准备:演示表结构与测试数据
在开始学习CRUD前,先创建演示表并插入测试数据,请先执行以下SQL,确保你的数据库中存在这两张表和对应数据,后续所有示例均依赖此环境。
1. 创建部门表(dept)
sql
-- 部门表:存储部门编号、部门名称、部门所在地
CREATE TABLE dept (
dept_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门编号(主键,自增)',
dept_name VARCHAR(50) NOT NULL COMMENT '部门名称(非空)',
location VARCHAR(100) COMMENT '部门所在地'
) COMMENT '部门表';
2. 创建员工表(emp)
sql
-- 员工表:存储员工编号、姓名、性别、薪资、入职日期、部门编号(外键关联部门表)
CREATE TABLE emp (
emp_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工编号(主键,自增)',
emp_name VARCHAR(50) NOT NULL COMMENT '员工姓名(非空)',
gender CHAR(1) DEFAULT '男' COMMENT '性别(默认男,可选男/女)',
salary DECIMAL(10,2) NOT NULL COMMENT '薪资(保留2位小数)',
hire_date DATE NOT NULL COMMENT '入职日期',
dept_id INT COMMENT '部门编号(外键,关联dept表的dept_id)',
-- 外键约束:员工的部门编号必须存在于部门表中
FOREIGN KEY (dept_id) REFERENCES dept(dept_id) ON DELETE SET NULL
) COMMENT '员工表';
3. 插入测试数据
sql
-- 向部门表插入3条测试数据
INSERT INTO dept (dept_name, location) VALUES
('研发部', '北京'),
('市场部', '上海'),
('人事部', '广州');
-- 向员工表插入6条测试数据
INSERT INTO emp (emp_name, gender, salary, hire_date, dept_id) VALUES
('张三', '男', 8000.00, '2023-01-15', 1),
('李四', '女', 6500.00, '2023-03-20', 1),
('王五', '男', 7000.00, '2023-02-10', 2),
('赵六', '男', 9000.00, '2022-11-05', 2),
('孙七', '女', 5000.00, '2023-05-30', 3),
('周八', '男', 12000.00, '2021-09-01', NULL); -- 周八暂未分配部门
什么是CRUD
CRUD是数据库操作的四大核心支柱,对应英文单词的首字母缩写,覆盖了数据从"创建"到"删除"的全生命周期,是所有数据库开发、数据分析的基础能力:
- C(Create):插入数据,向表中添加新的记录,是数据的"诞生";
- R(Read):查询数据,从表中提取所需的记录,是使用频率最高的操作;
- U(Update):修改数据,更新表中已存在的记录,适配数据的"变化";
- D(Delete):删除数据,移除表中不需要的记录,完成数据的"清理"。
这四大操作中,查询(Read) 是语法最灵活、功能最强大的部分,也是学习的重点;增、改、删则重点关注数据安全性,避免误操作。
C - 数据插入(INSERT)
核心定义
INSERT 语句用于向数据库表中添加新的记录,可以插入单行、多行,甚至将其他查询的结果插入到表中。
通用语法框架
sql
INSERT INTO 表名 (字段1, 字段2, ..., 字段n)
VALUES (值1, 值2, ..., 值n);
语法说明:
- 字段列表必须与值列表一一对应(数量相同、顺序相同、类型匹配);
- 若字段设置了非空约束(NOT NULL),必须在插入时为其赋值;
- 若字段设置了自增(AUTO_INCREMENT) 、默认值(DEFAULT),可省略该字段,数据库会自动填充。
3.1 单行插入(基础用法)
适用场景:仅需添加一条记录,是最基础的插入方式。
示例1:指定所有字段插入(含自增字段)
sql
-- 向部门表插入一条记录,手动指定自增字段dept_id(需确保未被使用)
INSERT INTO dept (dept_id, dept_name, location)
VALUES (4, '财务部', '深圳');
执行结果:部门表新增一条"财务部"记录,dept_id为4。
示例2:省略自增字段插入(推荐)
sql
-- 自增字段dept_id由数据库自动生成,无需手动指定
INSERT INTO dept (dept_name, location)
VALUES (5, '运维部', '杭州');
执行结果:部门表新增"运维部"记录,dept_id自动为5(延续自增序列)。
示例3:使用默认值插入
sql
-- 员工表的gender字段有默认值'男',插入时可省略
INSERT INTO emp (emp_name, salary, hire_date, dept_id)
VALUES ( '吴九', 7500.00, '2023-06-10', 4);
执行结果:吴九的gender字段自动填充为'男'。
3.2 批量插入(高效用法)
适用场景 :需要添加多条记录,相比单行插入,批量插入仅需一次数据库请求,效率提升数倍。
语法
sql
INSERT INTO 表名 (字段1, 字段2, ...)
VALUES (值1, 值2, ...),
(值3, 值4, ...),
(值5, 值6, ...);
示例
sql
-- 向员工表批量插入3条记录
INSERT INTO emp (emp_name, gender, salary, hire_date, dept_id)
VALUES ( '郑十', '女', 6800.00, '2023-04-01', 5),
( '钱十一', '男', 9500.00, '2022-08-15', 1),
( '孙十二', '女', 8200.00, '2023-01-05', 2);
执行结果:员工表一次性新增3条记录,无需执行3次INSERT语句。
3.3 插入查询结果(进阶用法)
适用场景:将一张表的查询结果,直接插入到另一张表中(需确保两张表的字段类型匹配),常用于数据备份、数据迁移。
语法
sql
INSERT INTO 目标表名 (字段1, 字段2, ...)
SELECT 字段1, 字段2, ... FROM 源表名 WHERE 筛选条件;
示例
sql
-- 步骤1:创建员工备份表(结构与emp一致)
CREATE TABLE emp_backup LIKE emp;
-- 步骤2:将emp表中薪资大于8000的员工,插入到emp_backup中
INSERT INTO emp_backup (emp_name, gender, salary, hire_date, dept_id)
SELECT emp_name, gender, salary, hire_date, dept_id FROM emp WHERE salary > 8000;
执行结果:emp_backup表中会包含张三、赵六、周八、钱十一等薪资超8000的员工记录。
3.4 INSERT避坑核心要点
- 非空字段必须赋值:若插入时省略非空字段,数据库会直接报错;
- 外键约束要遵守:如向emp表插入dept_id=10的记录(部门表无此编号),会因外键约束失败;
- 自增字段不要重复赋值:手动指定自增字段值时,需确保未被占用,否则会主键冲突;
- 字段类型要匹配:如向DATE类型的hire_date字段插入'2023/01/01'(字符串格式错误),会插入失败。
R - 数据查询(SELECT)
核心定义
SELECT 语句用于从一个或多个表中查询并提取数据,是数据库中使用频率最高、语法最复杂的操作。通过组合不同的子句,可实现从"简单查询"到"复杂数据分析"的所有需求。
完整语法框架
sql
SELECT [DISTINCT] 字段1 [AS 别名1], 字段2 [AS 别名2], ...
FROM 表名1 [别名1]
[JOIN 表名2 [别名2] ON 联查条件] -- 多表联查
[WHERE 行筛选条件] -- 分组前筛选
[GROUP BY 分组字段1, 分组字段2, ...] -- 分组
[HAVING 分组筛选条件] -- 分组后筛选
[ORDER BY 排序字段1 [ASC/DESC], 排序字段2 [ASC/DESC], ...] -- 排序
[LIMIT 偏移量, 行数]; -- 限制结果数
执行顺序(关键) :FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。
4.1 基础查询:字段与表的核心关联
适用场景:查询表中的基础字段数据,无需筛选、排序,是查询的入门用法。
示例1:查询所有字段(* 通配符)
sql
-- 查询部门表的所有字段、所有记录
SELECT * FROM dept;
注意 :仅用于测试/临时查询,生产环境禁止使用 通配符,需明确指定字段(避免查询无用字段,提升效率)。
示例2:查询指定字段
sql
-- 查询员工表的姓名、薪资、入职日期
SELECT emp_name, salary, hire_date FROM emp;
示例3:使用别名(AS)简化结果
sql
-- 给字段起别名,让查询结果更易读(AS可省略)
SELECT emp_name AS 员工姓名, salary 薪资, hire_date 入职日期 FROM emp;
示例4:去重查询(DISTINCT)
sql
-- 查询员工表中所有的部门编号,去除重复值(查看有哪些部门有员工)
SELECT DISTINCT dept_id FROM emp;
执行结果:仅显示1、2、3、4、5、NULL,无重复值。
4.2 条件查询:WHERE子句全解析
适用场景 :筛选出符合条件的记录,是查询的核心子句之一。WHERE 支持比较运算符 、逻辑运算符 、模糊查询 、范围查询等。
常用运算符汇总
| 类型 | 运算符 | 说明 |
|---|---|---|
| 比较运算符 | =, !=/<> , >, <, >=, <= | 等于、不等于、大于、小于等 |
| 逻辑运算符 | AND, OR, NOT | 且、或、非 |
| 模糊查询 | LIKE | 搭配%(任意字符)、_(单个字符) |
| 范围查询 | IN, BETWEEN ... AND ... | 匹配列表、在指定范围内 |
| 空值查询 | IS NULL, IS NOT NULL | 字段为空、字段不为空 |
示例1:比较运算符查询
sql
-- 查询薪资大于8000的员工姓名和薪资
SELECT emp_name, salary FROM emp WHERE salary > 8000;
示例2:逻辑运算符查询
sql
-- 查询研发部(dept_id=1)且薪资大于7000的员工
SELECT emp_name, salary, dept_id FROM emp WHERE dept_id = 1 AND salary > 7000;
-- 查询研发部(dept_id=1)或市场部(dept_id=2)的员工
SELECT emp_name, dept_id FROM emp WHERE dept_id = 1 OR dept_id = 2;
示例3:模糊查询(LIKE)
sql
-- 查询姓名以"张"开头的员工(%匹配任意字符)
SELECT emp_name FROM emp WHERE emp_name LIKE '张%';
-- 查询姓名第二个字是"三"的员工(_匹配单个字符)
SELECT emp_name FROM emp WHERE emp_name LIKE '_三';
示例4:范围查询
sql
-- 方式1:IN - 查询部门编号为1、3、5的员工
SELECT emp_name, dept_id FROM emp WHERE dept_id IN (1, 3, 5);
-- 方式2:BETWEEN ... AND ... - 查询薪资在6000到9000之间的员工(包含边界)
SELECT emp_name, salary FROM emp WHERE salary BETWEEN 6000 AND 9000;
示例5:空值查询
sql
-- 查询未分配部门的员工(dept_id为NULL)
SELECT emp_name FROM emp WHERE dept_id IS NULL;
-- 查询已分配部门的员工
SELECT emp_name FROM emp WHERE dept_id IS NOT NULL;
注意 :NULL不能用=判断,必须用IS NULL/IS NOT NULL。
4.3 排序查询:ORDER BY的精准使用
适用场景:将查询结果按指定字段排序,便于查看数据规律(如按薪资从高到低排名)。
语法
sql
ORDER BY 排序字段1 [ASC/DESC], 排序字段2 [ASC/DESC]
ASC:升序(默认,从小到大);DESC:降序(从大到小);- 支持多字段排序:先按第一个字段排序,若第一个字段值相同,再按第二个字段排序。
示例1:单字段升序/降序
sql
-- 按薪资升序排序(默认ASC)
SELECT emp_name, salary FROM emp ORDER BY salary;
-- 按薪资降序排序
SELECT emp_name, salary FROM emp ORDER BY salary DESC;
示例2:多字段排序
sql
-- 先按部门编号升序,再按薪资降序排序
SELECT emp_name, dept_id, salary FROM emp ORDER BY dept_id ASC, salary DESC;
4.4 限制结果:LIMIT分页与行限制
适用场景 :仅查询前N条记录,或实现分页功能(如网页的第1页、第2页数据),是开发中必备的用法。
语法
sql
-- 方式1:仅限制行数(取前n条)
LIMIT n;
-- 方式2:分页(从第offset条开始,取n条;offset从0开始)
LIMIT offset, n;
示例1:取前3条记录
sql
-- 查询薪资最高的前3名员工
SELECT emp_name, salary FROM emp ORDER BY salary DESC LIMIT 3;
示例2:分页查询(实战)
sql
-- 分页:第1页,每页5条(offset=0,取5条)
SELECT emp_name, salary FROM emp ORDER BY emp_id LIMIT 0, 5;
-- 分页:第2页,每页5条(offset=5,取5条)
SELECT emp_name, salary FROM emp ORDER BY emp_id LIMIT 5, 5;
4.5 分组查询:GROUP BY与聚合函数
适用场景 :对数据进行分组统计 (如统计每个部门的员工人数、平均薪资),核心是聚合函数 +GROUP BY。
常用聚合函数
| 函数名 | 说明 |
|---|---|
| COUNT(*) | 统计分组内的记录数 |
| SUM(字段) | 计算分组内字段的总和 |
| AVG(字段) | 计算分组内字段的平均值 |
| MAX(字段) | 取分组内字段的最大值 |
| MIN(字段) | 取分组内字段的最小值 |
核心规则
GROUP BY 后接分组字段 ,SELECT 后只能出现:分组字段、聚合函数,不能出现其他普通字段。
示例1:基础分组统计
sql
-- 统计每个部门的员工人数
SELECT dept_id AS 部门编号, COUNT(*) AS 员工人数
FROM emp
GROUP BY dept_id;
示例2:多聚合函数分组统计
sql
-- 统计每个部门的员工人数、平均薪资、最高薪资
SELECT dept_id AS 部门编号,
COUNT(*) AS 员工人数,
AVG(salary) AS 平均薪资,
MAX(salary) AS 最高薪资
FROM emp
GROUP BY dept_id;
示例3:多字段分组(进阶)
sql
-- 统计每个部门、每个性别的员工人数(先按部门分组,再按性别分组)
SELECT dept_id AS 部门编号,
gender AS 性别,
COUNT(*) AS 员工人数
FROM emp
GROUP BY dept_id, gender;
4.6 分组过滤:HAVING与WHERE的区别
核心问题 :WHERE 不能筛选聚合函数的结果,此时需要HAVING。
| 特性 | WHERE | HAVING |
|---|---|---|
| 执行时机 | 分组前筛选 | 分组后筛选 |
| 筛选对象 | 单个行记录 | 分组后的结果集 |
| 聚合函数 | 不支持使用 | 支持使用 |
| 依赖关系 | 可独立使用 | 必须跟在GROUP BY后 |
示例1:仅用HAVING筛选分组结果
sql
-- 统计每个部门的平均薪资,筛选出平均薪资大于7500的部门
SELECT dept_id AS 部门编号, AVG(salary) AS 平均薪资
FROM emp
GROUP BY dept_id
HAVING AVG(salary) > 7500;
示例2:WHERE + HAVING 组合使用(实战常用)
sql
-- 先筛选出入职日期在2022年及以后的员工,再按部门分组,最后筛选出员工人数大于2的部门
SELECT dept_id AS 部门编号, COUNT(*) AS 员工人数
FROM emp
WHERE hire_date >= '2022-01-01' -- 分组前:筛选2022年及以后入职的员工
GROUP BY dept_id
HAVING COUNT(*) > 2; -- 分组后:筛选员工人数大于2的部门
4.7 多表联查:JOIN的三种核心类型
适用场景:数据分布在多张表中,需要关联查询(如查询员工姓名的同时,查询其所属部门名称)。
三种核心JOIN类型
- INNER JOIN(内连接) :只返回两张表中匹配关联条件的记录;
- LEFT JOIN(左连接):返回左表的所有记录,右表匹配的记录显示,不匹配则显示NULL;
- RIGHT JOIN(右连接):返回右表的所有记录,左表匹配的记录显示,不匹配则显示NULL。
示例1:INNER JOIN(内连接)
sql
-- 查询员工姓名、薪资,以及所属部门名称(仅显示有部门的员工)
SELECT e.emp_name, e.salary, d.dept_name
FROM emp e -- 给emp表起别名e
INNER JOIN dept d -- 给dept表起别名d
ON e.dept_id = d.dept_id; -- 关联条件:员工的部门编号=部门的部门编号
示例2:LEFT JOIN(左连接)
sql
-- 查询所有员工的姓名,以及所属部门名称(包括未分配部门的员工)
SELECT e.emp_name, d.dept_name
FROM emp e
LEFT JOIN dept d
ON e.dept_id = d.dept_id;
执行结果:周八的dept_name显示为NULL(因其dept_id为NULL)。
示例3:RIGHT JOIN(右连接)
sql
-- 查询所有部门的名称,以及部门下的员工姓名(包括无员工的部门)
SELECT d.dept_name, e.emp_name
FROM emp e
RIGHT JOIN dept d
ON e.dept_id = d.dept_id;
U - 数据修改(UPDATE)
核心定义
UPDATE 语句用于修改表中已存在的记录,可以修改单条记录、多条记录,甚至结合查询结果批量修改。
通用语法框架
sql
UPDATE 表名 [别名]
SET 字段1 = 新值1, 字段2 = 新值2, ...
[WHERE 筛选条件]
[JOIN 表名2 ON 联查条件]; -- 多表关联修改
5.1 单表修改(基础用法)
适用场景:修改表中单个字段的数值。
示例
sql
-- 将孙七的薪资修改为5500
UPDATE emp
SET salary = 5500
WHERE emp_name = '孙七';
5.2 多字段同时修改
适用场景:需要同时更新一条记录的多个字段。
示例
sql
-- 将吴九的部门修改为研发部(dept_id=1),薪资修改为8000
UPDATE emp
SET dept_id = 1, salary = 8000
WHERE emp_name = '吴九';
5.3 结合WHERE的精准修改(核心)
这是UPDATE最关键的用法 :若省略WHERE,会修改表中所有记录,造成不可挽回的损失!
示例1:按条件批量修改
sql
-- 给研发部(dept_id=1)的所有员工涨薪10%
UPDATE emp
SET salary = salary * 1.1
WHERE dept_id = 1;
示例2:结合多条件修改
sql
-- 给市场部(dept_id=2)入职时间在2023年及以后的员工,薪资增加500
UPDATE emp
SET salary = salary + 500
WHERE dept_id = 2 AND hire_date >= '2023-01-01';
5.4 结合聚合函数的批量修改(进阶)
适用场景:根据分组统计的结果,修改对应记录(需结合子查询)。
示例
sql
-- 将平均薪资最低的部门的所有员工,薪资增加300
-- 步骤1:查询平均薪资最低的部门编号
-- 步骤2:根据部门编号修改员工薪资
UPDATE emp
SET salary = salary + 300
WHERE dept_id = (
SELECT dept_id FROM emp GROUP BY dept_id ORDER BY AVG(salary) LIMIT 1
);
5.5 UPDATE避坑核心要点
- 永远不要省略WHERE :修改前先执行
SELECT验证筛选条件,确认无误后再执行UPDATE; - 使用事务保护 :生产环境修改数据时,先执行
BEGIN(开启事务),修改后验证数据,再执行COMMIT(提交事务),若出错则执行ROLLBACK(回滚); - 外键关联要注意:修改外键字段时,需确保新值存在于关联表中,否则会约束失败;
- 避免修改主键:主键是表的唯一标识,修改主键可能导致数据关联混乱,除非特殊需求,否则禁止修改。
D - 数据删除(DELETE)
核心定义
DELETE 语句用于从表中删除已存在的记录,可以删除单条、多条记录,也可以多表关联删除。
通用语法框架
sql
DELETE 表名1.* -- 明确删除哪个表的记录(多表联删时必须指定)
FROM 表名1 [别名]
[JOIN 表名2 [别名] ON 联查条件]
[WHERE 筛选条件];
6.1 单条记录删除(基础用法)
适用场景:删除表中指定的一条记录。
示例
sql
-- 删除emp_backup表中姓名为"周八"的记录
DELETE FROM emp_backup
WHERE emp_name = '周八';
6.2 批量记录删除
适用场景:删除符合条件的多条记录。
示例1:按简单条件删除
sql
-- 删除emp表中未分配部门的员工(dept_id IS NULL)
DELETE FROM emp
WHERE dept_id IS NULL;
示例2:按复杂条件删除
sql
-- 删除薪资低于6000且入职时间在2023年5月以后的员工
DELETE FROM emp
WHERE salary < 6000 AND hire_date > '2023-05-01';
6.3 多表关联删除(进阶)
适用场景:删除主表记录的同时,删除从表中关联的记录(或仅删除从表记录)。
示例1:删除部门的同时,删除该部门下的所有员工
sql
-- 关联dept和emp表,删除dept_id=5的部门,以及该部门下的所有员工
DELETE d.*, e.*
FROM dept d
JOIN emp e ON d.dept_id = e.dept_id
WHERE d.dept_id = 5;
示例2:仅删除某部门下的员工,保留部门
sql
-- 删除研发部(dept_id=1)下薪资低于7000的员工
DELETE e.*
FROM emp e
JOIN dept d ON e.dept_id = d.dept_id
WHERE d.dept_name = '研发部' AND e.salary < 7000;
6.4 DELETE与TRUNCATE的区别(关键)
很多同学会混淆这两个删除语句,核心区别如下,务必牢记:
| 特性 | DELETE | TRUNCATE |
|---|---|---|
| 操作类型 | DML(数据操作语言) | DDL(数据定义语言) |
| 可回滚 | 支持(开启事务时) | 不支持(直接清空,无法回滚) |
| 自增字段 | 自增序列保留(继续从上次值递增) | 自增序列重置(从1开始) |
| 触发触发器 | 会触发(如删除前的校验触发器) | 不会触发 |
| 适用场景 | 精准删除部分记录 | 清空整张表(无筛选条件) |
示例:TRUNCATE清空表
sql
-- 清空emp_backup表(谨慎使用!)
TRUNCATE TABLE emp_backup;
6.5 DELETE避坑核心要点
- 必加WHERE条件:和UPDATE一样,省略WHERE会删除表中所有记录;
- 先查后删:删除前用SELECT验证筛选条件,确认要删除的记录;
- 慎用TRUNCATE:TRUNCATE无法回滚,且会重置自增序列,生产环境需经审批后使用;
- 外键约束影响 :若从表有记录关联主表,直接删除主表记录会失败(需先删从表关联记录,或设置外键为
ON DELETE CASCADE(级联删除))。
CRUD综合实战案例
结合以上所有知识点,完成一个实战场景:针对员工管理系统,实现以下操作,综合运用CRUD。
实战需求
- 新增一个"技术支持部",所在地为"成都";
- 查询所有部门的名称和员工人数,按员工人数降序排序;
- 将"技术支持部"的所有员工(先插入2名)薪资设置为7000;
- 删除"人事部"(dept_id=3)下薪资低于5500的员工;
- 最终查询所有员工的姓名、薪资、部门名称,按部门名称升序排序。
分步实现SQL
sql
-- 1. 新增技术支持部
INSERT INTO dept (dept_name, location) VALUES ('技术支持部', '成都');
-- 2. 向技术支持部插入2名员工(假设新部门dept_id=6)
INSERT INTO emp (emp_name, gender, salary, hire_date, dept_id) VALUES
('李十三', '男', 6000.00, '2023-07-01', 6),
('王十四', '女', 6500.00, '2023-07-10', 6);
-- 3. 查询所有部门的名称和员工人数,按员工人数降序排序
SELECT d.dept_name AS 部门名称, COUNT(e.emp_id) AS 员工人数
FROM dept d
LEFT JOIN emp e ON d.dept_id = e.dept_id
GROUP BY d.dept_name
ORDER BY 员工人数 DESC;
-- 4. 将技术支持部的所有员工薪资设置为7000
UPDATE emp e
JOIN dept d ON e.dept_id = d.dept_id
SET e.salary = 7000
WHERE d.dept_name = '技术支持部';
-- 5. 删除人事部(dept_id=3)下薪资低于5500的员工
DELETE e.*
FROM emp e
WHERE e.dept_id = 3 AND e.salary < 5500;
-- 6. 最终查询所有员工的姓名、薪资、部门名称,按部门名称升序排序
SELECT e.emp_name AS 员工姓名, e.salary AS 薪资, d.dept_name AS 部门名称
FROM emp e
LEFT JOIN dept d ON e.dept_id = d.dept_id
ORDER BY d.dept_name ASC;
核心知识点速记表
| 操作 | 核心关键字 | 最关键注意点 | 核心子句/函数 |
|---|---|---|---|
| 插入 | INSERT | 非空字段必赋值,字段与值一一对应 | VALUES、批量插入用逗号分隔 |
| 查询 | SELECT | 执行顺序,WHERE与HAVING的区别 | GROUP BY、JOIN、LIMIT |
| 修改 | UPDATE | 永远不要省略WHERE,先查后改 | SET、子查询 |
| 删除 | DELETE | 必加WHERE,区分DELETE与TRUNCATE | JOIN、TRUNCATE(慎用) |