02-数据库学习笔记(SQL引擎)

一.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(总长度,小数位)
  • 日期:DATEDATETIME
  • 布尔:用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) 就能实现。

相关推荐
六点_dn6 小时前
RabbitMQ学习笔记-定义与作用
笔记·学习·rabbitmq
我的xiaodoujiao7 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
笃行3507 小时前
国产化落地避坑 · 干货向|Oracle 迁金仓 KES,我把外连接消除排在隐性陷阱第一位
数据库
老纪的技术唠嗑局8 小时前
花一年时间整理出的:AI 数据库混合搜索入门实践
数据库
川石课堂软件测试8 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
世人万千丶8 小时前
鸿蒙Flutter Flexible与Expanded的区别
学习·flutter·harmonyos·鸿蒙
笃行3509 小时前
国产化落地避坑 · 干货向|迁移后那条「测试能过、一上生产就查空」的 SQL,多半栽在 WHERE 函数顺序上
数据库
香辣牛肉饭9 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
迷途呀9 小时前
Python:函数中的参数类型
开发语言·笔记·python·langchain·nlp