05- SQL 增删改查与核心语法讲解

下面按「增删改查 → 条件与排序 → 聚合 → 关联 → 分组 → 事务 → 索引」的顺序说明,不依赖你项目里的任何文件。


一、增删改查(CRUD)

1. 查 --- SELECT(Read)

复制代码
SELECT 列1, 列2 FROM 表名;

SELECT * FROM users;                    -- 查所有列
SELECT name, email FROM users;          -- 查指定列

2. 增 --- INSERT(Create)

复制代码
INSERT INTO users (name, email, age)
VALUES ('张三', 'zhangsan@example.com', 25);

-- 一次插入多行
INSERT INTO users (name, email) VALUES
('李四', 'lisi@example.com'),
('王五', 'wangwu@example.com');

3. 改 --- UPDATE(Update)

复制代码
UPDATE users
SET age = 26, email = 'new@example.com'
WHERE id = 1;   -- 几乎总是要带 WHERE,否则整表都会被改

4. 删 --- DELETE(Delete)

复制代码
DELETE FROM users WHERE id = 1;   -- 删指定行
DELETE FROM users;                -- 删全表(慎用)

二、条件筛选:WHERE、AND、BETWEEN

WHERE --- 过滤行

复制代码
SELECT * FROM users WHERE age > 18;
SELECT * FROM users WHERE city = '北京';
SELECT * FROM users WHERE email IS NULL;
SELECT * FROM users WHERE name LIKE '张%';   -- 模糊匹配

AND / OR --- 组合条件

复制代码
SELECT * FROM users
WHERE age >= 18 AND city = '上海';

SELECT * FROM users
WHERE status = 'active' OR status = 'pending';

BETWEEN --- 范围(含边界)

复制代码
SELECT * FROM orders
WHERE amount BETWEEN 100 AND 500;
-- 等价于:amount >= 100 AND amount <= 500

SELECT * FROM users
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';

IN / NOT IN --- 枚举多个值

复制代码
SELECT * FROM users WHERE city IN ('北京', '上海', '广州');

三、排序与分页:ORDER BY、ASC、DESC、LIMIT

ORDER BY --- 排序

复制代码
SELECT * FROM users ORDER BY age ASC;    -- 升序(默认)
SELECT * FROM users ORDER BY age DESC;   -- 降序

-- 多列排序:先按 city,再按 age 降序
SELECT * FROM users
ORDER BY city ASC, age DESC;
关键字 含义
ASC 升序(小→大,A→Z)
DESC 降序(大→小,Z→A)

LIMIT --- 限制返回行数(分页常用)

复制代码
-- MySQL / PostgreSQL 常见写法
SELECT * FROM users ORDER BY id LIMIT 10;                    -- 前 10 条
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;          -- 跳过 20 条,取 10 条(第 3 页)

-- SQL Server 用 TOP 或 OFFSET/FETCH
-- Oracle 用 FETCH FIRST n ROWS ONLY

四、聚合函数:SUM、AVG、MAX、MIN

对一列或多列做统计,通常配合 GROUP BY 或单独用在整表/筛选结果上。

复制代码
-- 全表统计
SELECT
  COUNT(*) AS total_users,
  AVG(age) AS avg_age,
  MAX(age) AS max_age,
  MIN(age) AS min_age,
  SUM(salary) AS total_salary
FROM users;

-- 带条件
SELECT AVG(amount) FROM orders WHERE status = 'completed';
函数 作用
COUNT(*) 行数
SUM(col) 求和
AVG(col) 平均值
MAX(col) 最大值
MIN(col) 最小值

注意: AVG 会忽略 NULLCOUNT(*) 计所有行,COUNT(col) 只计该列非 NULL 的行。


五、表关联:JOIN

当数据分布在多张表时,用 JOIN 按关联键把行拼在一起。

假设:

  • users(id, name)

  • orders(id, user_id, amount)

INNER JOIN --- 只保留两边都能匹配上的行

复制代码
SELECT u.name, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

LEFT JOIN --- 左表全保留,右表无匹配则为 NULL

复制代码
SELECT u.name, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- 即使用户没有订单也会出现在结果里

RIGHT JOIN --- 右表全保留

复制代码
SELECT u.name, o.amount
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

多表关联

复制代码
SELECT u.name, p.product_name, o.amount
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;

要点: ON 后面写关联条件(通常是外键 = 主键);WHERE 写业务过滤条件。


六、GROUP BY --- 分组聚合

按某一列(或多列)分组,再对每组做 SUM / AVG / COUNT 等。

示例数据

假设 users 表当前数据如下:

id name city age
1 张三 北京 25
2 李四 北京 30
3 王五 北京 28
4 赵六 上海 22
5 孙七 上海 35
6 周八 广州 40
7 吴九 北京 26
8 郑十 北京 32
9 钱一 北京 24
10 陈二 北京 29
11 刘三 北京 27
12 黄四 北京 31
13 林五 北京 23
14 何六 北京 33

北京 11 人、上海 2 人、广州 1 人,便于演示 HAVING 过滤。

示例 1:按城市统计人数与平均年龄

复制代码
-- 每个城市的用户数量和平均年龄
SELECT
  city,
  COUNT(*) AS user_count,
  AVG(age) AS avg_age
FROM users
GROUP BY city;

执行顺序(逻辑步骤,不是写 SQL 的顺序):

步骤 子句 本例做了什么
1 FROM 读取 users 全部 14 行
2 WHERE 无,跳过
3 GROUP BY city 分成 3 组:北京 11 行、上海 2 行、广州 1 行
4 HAVING 无,跳过
5 SELECT 每组计算 COUNT(*)AVG(age),输出 city
6 ORDER BY 无,跳过
7 LIMIT 无,跳过

分组过程示意:

复制代码
北京组 → 11 行 → COUNT(*)=11, AVG(age)=(25+30+28+26+32+24+29+27+31+23+33)/11 = 28.00
上海组 →  2 行 → COUNT(*)=2,  AVG(age)=(22+35)/2 = 28.50
广州组 →  1 行 → COUNT(*)=1,  AVG(age)=40.00

查询结果:

city user_count avg_age
北京 11 27.36
上海 2 28.50
广州 1 40.00

示例 2:HAVING 过滤分组结果

复制代码
-- 配合 HAVING 过滤分组结果(类似 WHERE,但针对聚合后的组)
SELECT city, COUNT(*) AS cnt
FROM users
GROUP BY city
HAVING COUNT(*) > 10;

HAVING 过滤示意:

复制代码
北京组 → COUNT(*)=11 → 11 > 10 ✓ 保留
上海组 → COUNT(*)=2  → 2 > 10  ✗ 丢弃
广州组 → COUNT(*)=1  → 1 > 10  ✗ 丢弃

查询结果:

city cnt
北京 11

记忆口诀:FROM 拿表 → WHERE 筛行 → GROUP BY 分组 → HAVING 筛组 → SELECT 选列 → ORDER BY 排序 → LIMIT 截断。

WHERE vs HAVING

关键字 作用
WHERE 分组之前过滤行
HAVING 分组之后过滤组