一.SQL语言分类
按照功能可分为四大类:
| 类别 | 作用 | 例子 |
|---|---|---|
| DML数据操纵语言 | 数据操作 | SELECT, INSERT, UPDATE, DELETE |
| DDL数据定义语言 | 数据结构定义 | CREAT,TABLE, ALTER, DROP |
| DCL数据控制语言 | 权限控制 | GRANT, REVOKE |
| TCL事务控制语言 | ----- | COMMIT、ROLLBACK、SAVEPOINT |
二.基础DDL:库,表操作
1.数据库操作
sql
-- 创建数据库
CREATE DATABASE test_db;
-- 查看所有数据库
SHOW DATABASES;
-- 使用数据库
USE test_db;
-- 删除数据库
DROP DATABASE IF EXISTS test_db;
2.常用数据类型(MySQL)
- 整数:
INT,BIGINT - 字符串:
VARCHAR(长度),CHAR - 小数:
DECIMAL(总长度,小数位) - 日期:
DATE、DATETIME - 布尔:用
TINYINT(1)0 假 1 真
3. 创建表 CREATE TABLE
sql
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键自增,唯一标识
name VARCHAR(20) NOT NULL, -- 非空
age INT DEFAULT 18, -- 默认值18
score DECIMAL(5,2),
create_time DATETIME
);
约束关键字:
PRIMARY KEY:主键(唯一且非空)
NOT NULL:不能为空
DEFAULT:默认值
UNIQUE:唯一值
FOREIGN KEY:外键(表关联)
4. 修改表 ALTER
sql
-- 新增字段
ALTER TABLE student ADD email VARCHAR(50);
-- 修改字段类型
ALTER TABLE student MODIFY email VARCHAR(100);
-- 修改字段名
ALTER TABLE student CHANGE email mail VARCHAR(100);
-- 删除字段
ALTER TABLE student DROP mail;
5. 删除表
sql
DROP TABLE IF EXISTS student;
三.DML:增、改、删(操作表中数据)
1. 插入 INSERT
sql
-- 指定字段插入
INSERT INTO student(name,age,score) VALUES ('张三',20,92.5);
-- 全字段插入(顺序必须和表一致)
INSERT INTO student VALUES (2,'李四',19,88.0,'2026-01-01 10:00:00');
-- 批量插入
INSERT INTO student(name,age)
VALUES ('王五',18),('赵六',21);
2. 更新 UPDATE
- 不加
WHERE会全表更新!
sql
-- 修改id=1的学生分数
UPDATE student SET score=95 WHERE id=1;
-- 多字段同时修改
UPDATE student SET age=20,score=90 WHERE name='张三';
3. 删除 DELETE
- 不加
WHERE清空整张表
sql
DELETE FROM student WHERE id=3;
-- 清空表(不重置自增主键)
DELETE FROM student;
-- 快速清空表,重置自增,不可回滚
TRUNCATE TABLE student;
四.核心 DQL:SELECT 查询
1. 基础查询
sql
-- 查询所有列
SELECT * FROM student;
-- 查询指定列
SELECT id,name,score FROM student;
-- 起别名 AS
SELECT name AS 姓名, score 分数 FROM student;
-- 去重 DISTINCT
SELECT DISTINCT age FROM student;
2. WHERE 条件过滤
- 常用运算符:= != > < >= <=
- 逻辑符:AND OR NOT
- 模糊匹配:LIKE
sql
-- 分数大于90
SELECT * FROM student WHERE score > 90;
-- 年龄18或19
SELECT * FROM student WHERE age=18 OR age=19;
-- 姓名带"张" %匹配任意字符 _匹配单个字符
SELECT * FROM student WHERE name LIKE '张%';
-- 区间 between 包含两端
SELECT * FROM student WHERE score BETWEEN 80 AND 100;
-- 多值匹配 IN
SELECT * FROM student WHERE age IN (18,20,22);
-- 判断空值 NULL必须用IS NULL,不能用=NULL
SELECT * FROM student WHERE score IS NULL;
3. 排序 ORDER BY
sql
-- 分数升序(默认ASC)
SELECT * FROM student ORDER BY score ASC;
-- 分数降序 DESC
SELECT * FROM student ORDER BY score DESC;
-- 多条件排序:先分数降序,同分按年龄升序
SELECT * FROM student ORDER BY score DESC, age ASC;
4.嵌套查询
sql
SELECT 姓名 FROM 学生
WHERE 学号 IN (SELECT 学号 FROM 选课 WHERE 课程号='001');
五.常见聚合函数
1.什么是聚合函数
聚合函数的核心作用是对一组数据进行统计计算,最终返回单一结果,常用于数据统计分析场景。
2.五个核心聚合函数
COUNT () 统计行数
COUNT(*):统计表中所有行(包含 NULL)
COUNT(字段):统计该字段不为 NULL 的行数
sql
SELECT COUNT(*) FROM tb_user; -- 总人数
SELECT COUNT(name) FROM tb_user; -- 姓名不为空的人数
SUM () 求和
只计算数字类型,NULL 自动忽略
sql
SELECT SUM(age) FROM tb_user; -- 所有人年龄总和
AVG () 平均值
总和 ÷ 有效行数,自动跳过 NULL
sql
SELECT AVG(age) FROM tb_user; -- 平均年龄
MAX () 最大值
数字、字符串、日期都能用
sql
SELECT MAX(age) FROM tb_user; -- 最大年龄
MIN () 最小值
sql
SELECT MIN(age) FROM tb_user; -- 最小年龄
六.分组与过滤
1.分组(GROUP BY)
GROUP BY 的作用是把表中相同值的行归为一组,方便对每组数据单独用聚合函数统计,比如按性别分组统计男女人数。
2.过滤(WHERE&HAVING)
WHERE是在分组前过滤原始数据,比如只保留 18 岁以上的用户再分组;HAVING是在分组后过滤聚合结果,比如只保留人数大于 2 的分组。
WHERE 在分组前过滤原始数据,减少分组的数据量;HAVING 在分组后过滤统计结果,针对聚合后的分组做筛选。而且 WHERE 不能用聚合函数,HAVING 可以用,这也是两者的重要区别。
七.高级分组(GROUPING SETS)
1.核心作用
GROUPING SETS 是对多个分组维度进行组合统计的高级语法,相当于把多个GROUP BY 的结果合并起来,避免用 UNION ALL 拼接。比如订单表按 "用户 + 状态""用户""状态" 分别分组统计金额,用 GROUPING SETS 可以写成:
sql
SELECT user_id, status, SUM (amount) FROM tb_order
GROUP BY GROUPING SETS ((user_id, status), (user_id), (status));
这样会同时返回三个分组维度的统计结果。它比多次 GROUP BY 再 UNION ALL 更高效,因为只扫描一次表。
八.字符串操作(String Operation)
1.模式匹配
模式匹配即模糊查询,通过LIKE关键字配合特殊通配符,可实现各类模糊匹配需求,具体规则如下:
- %:匹配任意长度的字符串(包括空字符串),例如'%;@cs'可匹配"rza@cs""taylor@cs",甚至"@cs"(前缀为空)。
- _:匹配任意单个字符,仅能匹配一个字符,例如'*a@cs'可匹配"ra@cs""sa@cs",但无法匹配"rza@cs"(前缀为两个字符)。
比如 name LIKE ' 李 %' 能找出所有姓李的人,name LIKE '_明 ' 能找出第二个字是明的两个字姓名。
2.常用字符串操作函数
拼接字符串 CONCAT ()
作用:把多个文本拼在一起
sql
SELECT CONCAT('姓名:', name) FROM tb_user;
-- 结果:姓名:zhangsan
-- 拼接带分隔符 CONCAT_WS(分隔符, 字符串1, 字符串2)
SELECT CONCAT_WS('-','男',20)
-- 结果:男-20
大小写转换 UPPER / LOWER
UPPER():全部转大写
LOWER():全部转小写
sql
SELECT UPPER('mysql'); -- MYSQL
SELECT LOWER('MySQL'); -- mysql
截取子串 SUBSTRING / SUBSTR
语法:SUBSTRING(字符串, 起始位置, 截取长度)
⚠️ MySQL 字符串下标从 1 开始,不是 0
sql
SELECT SUBSTRING('abcdef',2,3); -- 从第2位取3个字符:bcd
获取字符串长度 LENGTH / CHAR_LENGTH
LENGTH():字节长度(中文一个汉字占 3 字节)
CHAR_LENGTH():字符个数(推荐统计文字个数)
sql
SELECT CHAR_LENGTH('数据库'); -- 3个字符
SELECT LENGTH('数据库'); -- 9个字节
替换字符串 REPLACE
REPLACE(原字符串, 要替换内容, 新内容)
sql
SELECT REPLACE('abc123','123','xyz'); -- abcxyz
查找字符串 POSITION/ LOCATE
查找子串在字符串中第一次出现的位置,找不到返回 0
sql
SELECT LOCATE('sql','mysql'); -- 2
九.日期与时间操作
不同数据库系统的日期时间操作语法差异较大,无统一标准
十.结果控制与输出重定向
1.排序(结果控制)
排序用 ORDER BY,默认升序,加 DESC 是降序,比如按年龄从大到小排:SELECT * FROM tb_user ORDER BY age DESC;
2.分页(结果控制)
分页就是把查询结果分成多页显示,避免一次性加载太多数据。比如查询 100 条用户数据,每页显示 10 条,就会分成 10 页,用户可以一页一页看。在 SQL 里用 LIMIT 实现,比如LIMIT 0,10 是第 1 页,LIMIT 10,10 是第 2 页,前面的数字是起始位置,后面是每页条数。
3.输出重定向(结果存储)
正常执行 SQL 查询,查询结果会直接打印在终端 / 软件界面上;
输出重定向:改变结果输出位置,不打印到屏幕,而是存入本地文件、服务器文件。
十一.横向连接 (LATERAL JOINS)
1.什么是横向连接
纵向:上下增加数据行(UNION 合并多条查询,上下拼接)
横向:左右拼接多张表的字段,把多张表的列合并到一张结果表,这就是 JOIN 横向连接。
两张表左右拼在一起,行不变、字段变多,属于横向合并。
举例:学生表(id,name)+ 成绩表(stu_id,score)横向连接,一行数据同时出现学生姓名 + 分数。
2.四种常用横向连接
准备两张测试表:
student:
| sid | name |
|---|---|
| 1 | 小明 |
| 2 | 小红 |
| 3 | 小刚 |
score(成绩)
| sid | score |
|---|---|
| 1 | 90 |
| 2 | 88 |
1. INNER JOIN 内连接
只保留两边都能匹配上的数据,两边没有对应数据直接丢弃。
结果只有小明、小红,小刚无成绩不显示。
2. LEFT JOIN 左外连接
左边表全部保留,右表匹配不到的字段填充 NULL。
小明、小红有分数,小刚 score 列显示 NULL。
3. RIGHT JOIN 右外连接
右边表全部保留,左表无匹配则为 NULL。
这里右表是成绩表,只会出现有成绩的学生。
4. CROSS JOIN 交叉连接(笛卡尔积)
不加匹配条件,左表每一行和右表每一行全部两两组合。
student 3 行,score 2 行,结果共 3×2=6 条记录,无业务意义,极少使用。
总结:
INNER JOIN:两边匹配才显示
LEFT JOIN:左表全部保留,右表匹配不上填 NULL
RIGHT JOIN:右表全部保留,左表匹配不上填 NULL
CROSS JOIN:无条件全部配对
十二.公用表表达式CTE
1.核心定义
CTE 就是用 WITH 定义一个临时查询结果,只在当前 SQL 里能用,能让复杂查询更清晰。比如 WITH t AS (SELECT * FROM student WHERE score>80),然后主查询直接用 t,代替嵌套子查询。
2.核心优势
可将复杂的子查询拆解为独立的CTE模块,使SQL代码逻辑更清晰、更易于维护,尤其适用于子查询嵌套层数较多的场景,能显著提升代码可读性。(可类比为宏定义)
十三.窗口函数(WINDOW FUNCTIONS)
1.核心特点
窗口函数能对一组数据进行计算,但不会像聚合函数那样合并行,而是每行都保留原数据并新增计算结果。
2.窗口函数与聚合函数的区别
- 聚合函数(如AVG、COUNT):将一组数据聚合为单一结果,例如按课程分组后,仅得到每门课程的平均绩点,每组对应一个结果。
- 窗口函数:不改变原始数据的行数,保留所有记录,仅对每一行数据计算其所在"窗口"的统计结果,例如为每门课程的学生按成绩排名,每一行数据均对应一个排名值,不丢失任何原始记录。
3.常用窗口函数
比如 ROW_NUMBER 给每行标序号,RANK 有并列排名会跳号,DENSE_RANK 并列不跳号;聚合类像 SUM、AVG 可以按窗口范围计算,比如SUM (score) OVER (PARTITION BY class_id)能算出每个学生所在班级的总分。使用时用 OVER () 指定窗口,PARTITION BY 分组,ORDER BY 排序。比如 "按班级分组给学生成绩排名",用 ROW_NUMBER () OVER (PARTITION BY class_id ORDER BY score DESC) 就能实现。