MySQL数据库管理、DDL、DQL、DML、DCL等总结

一、MySQL 管理

启动及关闭 MySQL 服务器

1. Windows 系统下

启动 MySQL 服务器:

1、通过 "服务" 管理工具: 打开"运行"对话框(Win + R),输入 services.msc,找到"MySQL"服务,右击选择"启动"。

2、通过命令提示符: 打开命令提示符(以管理员身份),输入以下命令:

bash 复制代码
net start mysql

关闭MySQL服务器:

1、**通过 "服务" 管理工具:**同样打开"运行"对话框,输入 services.msc,找到 "MySQL" 服务,右击选择"停止"。

2、通过命令提示符: 打开命令提示符(以管理员身份),输入以下命令:

bash 复制代码
net stop mysql

2. Linux 系统下

1、启动 MySQL 服务:

使用 systemd命令(适用于大多数现代 Linux 发行版,如 Ubuntu、CentOS 等):

bash 复制代码
sudo systemctl start mysql

使用 service 命令(在一些较旧的发行版中):

bash 复制代码
sudo service mysql start

2、关闭 MySQL 服务:

使用 systemd:

bash 复制代码
sudo systemctl stop mysql

使用 service 命令:

bash 复制代码
sudo service mysql stop

3、重启 MySQL 服务:

使用 systemd:

bash 复制代码
sudo systemctl restart mysql

使用 service 命令:

bash 复制代码
sudo service mysql restart

4、检查 MySQL 服务状态:

使用 systemd命令:

bash 复制代码
sudo systemctl status mysql

使用 service 命令:

bash 复制代码
sudo service mysql status

二、数据库和表的基本操作 (DDL - 数据定义语言)

数据定义语言(DDL)用于创建、修改和删除数据库对象(如数据库、表、索引等)。以下是 MySQL 中关于数据库和表的核心 DDL 操作详解:

1. 创建数据库:​CREATE DATABASE

功能:创建一个新的数据库。

基本语法

sql 复制代码
CREATE DATABASE|SCHEMA [IF NOT EXISTS] 数据库名 [CHARACTER SET 字符集] [COLLATE 排序规则];

选项说明

  • IF NOT EXISTS:如果数据库不存在才创建(避免重复创建报错)
  • CHARACTER SET:指定数据库默认字符集(如 utf8mb4 支持所有 Unicode 字符,包括 emoji)
  • COLLATE:指定字符集的排序规则(如 utf8mb4_general_ci 不区分大小写)

示例

sql 复制代码
--   创建一个新的数据库my_company。
CREATE DATABASE my_company;

-- 创建名为 mydb 的数据库,使用 utf8mb4 字符集
CREATE DATABASE IF NOT EXISTS mydb 
  CHARACTER SET utf8mb4 
  COLLATE utf8mb4_general_ci;

2. 查看数据库:​SHOW DATABASES

功能:查看所有的数据库信息。

基本语法

sql 复制代码
SHOW {DATABASE|SCHEMAS}[LIKE '模式' WHERE 条件];
  • 使用 SELECT DATABASES; 可查看服务器中的所有数据库。
  • 使用SELECT DATABASES LIEK 'db_%';筛选以db_开头的数据库名称

3. 选择数据库: USE

功能:指定当前操作的数据库(后续操作默认在此数据库中执行),当前数据库在工作会话关闭(即断开与该数据库的连接)或再次使用USE语句指定数据库时,结束工作状态。

基本语法

sql 复制代码
USE 数据库名;

示例

sql 复制代码
-- 选择 mydb 作为当前数据库
USE mydb;

提示:使用 SELECT DATABASE(); 可查看当前选中的数据库。

4. 创建表:CREATE TABLE

功能:在当前数据库中创建新表,需定义表名、列名、数据类型及约束。

基本语法

sql 复制代码
CREATE TABLE [IF NOT EXISTS] 表名 (
  列名1 数据类型 [约束],
  列名2 数据类型 [约束],
  ...
  [表级约束]
) [ENGINE=存储引擎];

常用数据类型

  • 字符串:VARCHAR(长度)(可变长度)、CHAR(长度)(固定长度)

  • 数值:INT(整数)、FLOAT/DOUBLE(浮点数)、DECIMAL(总位数, 小数位)(精确小数)

  • 日期时间:DATE(日期)、TIME(时间)、DATETIME(日期时间)、TIMESTAMP(带时区的时间戳)

  • 布尔:BOOLEAN(等价于 TINYINT(1),1 为真,0 为假)

常用约束

  • PRIMARY KEY:主键(唯一标识记录,非空且唯一)
  • NOT NULL:列值不能为空
  • UNIQUE:列值唯一(允许为空)
  • DEFAULT:默认值
  • AUTO_INCREMENT:自增(通常用于主键,插入时自动生成唯一值)
  • FOREIGN KEY:外键(关联其他表的主键,保证数据一致性)

示例:创建用户表

sql 复制代码
CREATE TABLE employees (
	id INT PRIMARY KEY AUTO_INCREMENT, 
	name VARCHAR(100), 
	salary DECIMAL(10,2));
sql 复制代码
CREATE TABLE IF NOT EXISTS users (
  id INT PRIMARY KEY AUTO_INCREMENT,  -- 自增主键
  username VARCHAR(50) NOT NULL UNIQUE,  -- 用户名唯一且非空
  email VARCHAR(100) NOT NULL UNIQUE,    -- 邮箱唯一且非空
  age INT DEFAULT NULL,  -- 年龄可为空,默认 NULL
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP  -- 创建时间默认当前时间
) ENGINE=InnoDB;  -- 使用 InnoDB 存储引擎(支持事务和外键)

5. 查看表结构​:DESCDESCRIBE

功能:显示表的列信息(字段名、数据类型、约束等)。

基本语法

sql 复制代码
DESC 表名;
-- 或
DESCRIBE 表名;

示例

sql 复制代码
-- 查看 users 表结构
DESC users;

输出示例:

plaintext 复制代码
+------------+--------------+------+-----+-------------------+-------------------+
| Field      | Type         | Null | Key | Default           | Extra             |
+------------+--------------+------+-----+-------------------+-------------------+
| id         | int          | NO   | PRI | NULL              | auto_increment    |
| username   | varchar(50)  | NO   | UNI | NULL              |                   |
| email      | varchar(100) | NO   | UNI | NULL              |                   |
| age        | int          | YES  |     | NULL              |                   |
| created_at | datetime     | YES  |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+------------+--------------+------+-----+-------------------+-------------------+

6. 修改表结构:ALTER TABLE

功能:修改已存在的表结构(添加 / 删除列、修改数据类型、添加约束等)。

常用操作语法

(1)修改数据库
sql 复制代码
-- 修改数据库mydb,使用utf8mb4字符集和utf8mb4_general_ci校验规则
ALTER DATABASE mydb 
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
(2)添加列
sql 复制代码
ALTER TABLE 表名 ADD 列名 数据类型 [约束];

示例:给 users 表添加 phone

sql 复制代码
ALTER TABLE users ADD phone VARCHAR(20) UNIQUE;
(3)删除列
sql 复制代码
ALTER TABLE 表名 DROP COLUMN 列名;

示例:删除 users 表的 age

sql 复制代码
ALTER TABLE users DROP COLUMN age;
(4)修改列的数据类型
sql 复制代码
ALTER TABLE 表名 MODIFY 列名 新数据类型 [约束];

示例:将 username 长度改为 100

sql 复制代码
ALTER TABLE users MODIFY username VARCHAR(100) NOT NULL UNIQUE;
(5)修改列名
sql 复制代码
ALTER TABLE 表名 CHANGE 旧列名 新列名 数据类型 [约束];

示例:将 phone 列改名为 mobile

sql 复制代码
ALTER TABLE users CHANGE phone mobile VARCHAR(20) UNIQUE;
(6)添加主键约束
sql 复制代码
ALTER TABLE 表名 ADD PRIMARY KEY (列名);
(7)添加外键约束(关联其他表)
sql 复制代码
-- 先创建关联表
CREATE TABLE orders (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  order_no VARCHAR(50) UNIQUE,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- 外键说明:orders.user_id 关联 users.id,当 users 中记录被删除时,关联的 orders 记录也会被删除(ON DELETE CASCADE)

7.删除表/数据库:DROP TABLE/ DROP DATABASE

功能 :永久删除表或数据库(操作不可逆,需谨慎!)。

基本语法

删除表
sql 复制代码
DROP TABLE [IF EXISTS] 表名;

示例:删除 orders 表

sql 复制代码
DROP TABLE IF EXISTS orders;
删除数据库
sql 复制代码
DROP DATABASE|SCHEMA [IF EXISTS] 数据库名;

示例:删除 mydb 数据库

sql 复制代码
DROP DATABASE IF EXISTS mydb;

警告:删除操作会永久删除所有数据,建议操作前备份!

注意

安装MySQL后,系统会自动创建4个名为performance_schema 、mysql、information_schema、sys的系统数据库

总结

DDL 操作是数据库设计和维护的基础,核心包括:

  • 数据库的创建(CREATE DATABASE)与删除(DROP DATABASE
  • 表的创建(CREATE TABLE)、结构修改(ALTER TABLE)与删除(DROP TABLE
  • 表结构的查看(DESC)和数据库的切换(USE

使用时需注意:

  • 优先使用 IF NOT EXISTSIF EXISTS 避免报错
  • 外键约束会影响数据操作性能,需根据实际场景选择
  • 生产环境中执行 DROP 操作前必须确认并备份数据

练习

基础题(入门级)

  1. 创建数据库 需求:创建一个名为 school 的数据库,使用 utf8mb4 字符集和 utf8mb4_general_ci 排序规则,要求如果数据库已存在则不报错。

  2. 选择与查看数据库 需求:切换到 school 数据库,并验证当前是否已选中该数据库。

  3. 创建基础表 需求:在 school 数据库中创建一个 students 表,包含以下字段:

    • id:整数,主键,自增
    • name:字符串(最长 50 字符),非空
    • gender:字符串(最长 10 字符),允许为空
    • birthdate:日期类型,允许为空
  4. 查看表结构 需求:查看 students 表的结构,确认字段名、数据类型和约束是否正确。

进阶题(基础操作综合)

  1. 修改表结构(添加列需求) :给 students 表添加一个 email 字段,要求:

    • 类型为字符串(最长 100 字符)
    • 唯一且非空
  2. 修改表结构(修改列) 需求:将 students 表中 gender 字段的类型修改为 CHAR(1)(只允许存储 ' 男 '/' 女 '/' 未 '),并设置默认值为 ' 未 '。

  3. 创建带约束的表 需求:在 school 数据库中创建 classes 表,包含以下字段:

    • class_id:整数,主键,自增
    • class_name:字符串(最长 30 字符),非空且唯一
    • teacher:字符串(最长 50 字符),允许为空
    • create_time:日期时间类型,默认值为当前系统时间

复杂题(多表关联与高级修改)

  1. 创建带外键的表 需求:创建 scores 表,用于记录学生成绩,包含以下字段:

    • score_id:整数,主键,自增
    • student_id:整数,非空(关联 students 表的 id
    • subject:字符串(最长 20 字符),非空
    • score:小数(总长度 5 位,保留 1 位小数),允许为空(缺考)
    • 要求添加外键约束:student_id 关联 students.id,当 students 表中某学生记录被删除时,scores 表中该学生的成绩记录也自动删除。
  2. 批量修改表结构 需求:对 scores 表执行以下修改:

    • 添加 exam_date 字段(日期类型,默认值为 2024-01-01
    • subject 字段的长度修改为 30 字符
    • 删除 score 字段的允许为空约束(设置为非空,缺考用 0 表示)
  3. 清理操作(删除) 需求:

    • 删除 classes 表(如果存在)

    • 最终删除 school 数据库(如果存在)

答案

基础题(入门级)

sql 复制代码
-- 创建school数据库
CREATE DATABASE IF NOT EXISTS school 
  CHARACTER SET utf8mb4 
  COLLATE utf8mb4_general_ci;

-- 选择并验证数据库
USE school;
SELECT DATABASE(); -- 验证当前选中的数据库

-- 创建students表
CREATE TABLE students (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10),
  birthdate DATE
);

-- 查看表结构
DESCRIBE students;
-- 或使用
SHOW COLUMNS FROM students;

进阶题(基础操作综合)

sql 复制代码
-- 添加email字段
ALTER TABLE students 
ADD COLUMN email VARCHAR(100) NOT NULL UNIQUE;

-- 修改gender字段
ALTER TABLE students 
MODIFY COLUMN gender CHAR(1) DEFAULT '未';

复杂题(多表关联与高级修改)

sql 复制代码
-- 创建classes表
CREATE TABLE classes (
  class_id INT PRIMARY KEY AUTO_INCREMENT,
  class_name VARCHAR(30) NOT NULL UNIQUE,
  teacher VARCHAR(50),
  create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 创建scores表(带外键约束)
CREATE TABLE scores (
  score_id INT PRIMARY KEY AUTO_INCREMENT,
  student_id INT NOT NULL,
  subject VARCHAR(20) NOT NULL,
  score DECIMAL(5,1),
  FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE
);

-- 批量修改scores表结构
ALTER TABLE scores
ADD COLUMN exam_date DATE DEFAULT '2024-01-01',
MODIFY COLUMN subject VARCHAR(30) NOT NULL,
MODIFY COLUMN score DECIMAL(5,1) NOT NULL DEFAULT 0;

-- 清理操作
DROP TABLE IF EXISTS classes;
DROP DATABASE IF EXISTS school;

代码说明:

  1. CREATE DATABASE IF NOT EXISTS 确保数据库存在时不会报错
  2. USE 命令用于切换数据库,SELECT DATABASE() 验证当前数据库
  3. 外键约束中 ON DELETE CASCADE 实现级联删除功能
  4. ALTER TABLE 语句可以组合多个修改操作,用逗号分隔
  5. 清理操作使用 DROP 命令,添加 IF EXISTS 避免报错

三、数据查询的进阶操作 (DQL - 数据查询语言)

1. 条件过滤​:WHERE

WHERE 用于在查询时筛选符合条件的记录,支持多种运算符,是精准提取数据的基础。

  • 核心语法SELECT 字段 FROM 表名 WHERE 条件表达式;
  • 支持的运算符
    • 比较运算符:=(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
    • 范围运算符:BETWEEN...AND...(在指定范围)、IN(值1,值2...)(在指定集合)、NOT IN(值1,值2...)(不在指定集合)
    • 空值判断:IS NULL(为空)、IS NOT NULL(不为空)
  • 示例 :查询 users 表中年龄在 20-30 岁之间、且邮箱不为空的用户
sql 复制代码
SELECT username, age, email FROM users 
WHERE age BETWEEN 20 AND 30 
AND email IS NOT NULL;

2. 结果排序​:ORDER BY

ORDER BY 用于对查询结果按指定字段排序,可控制升序或降序,让结果更具可读性。

  • 核心语法SELECT 字段 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2...;
  • 关键规则
    • 排序方式:ASC(升序,默认,可省略)、DESC(降序,必须显式声明)
    • 多字段排序:先按字段 1 排序,字段 1 值相同时,再按字段 2 排序
  • 示例 :查询 orders 表中所有订单,先按 "订单金额" 降序排,金额相同时按 "下单时间" 升序排
sql 复制代码
SELECT order_id, user_id, amount, create_time FROM orders 
ORDER BY amount DESC, create_time ASC;

3. 结果数量限制​: LIMIT

LIMIT 用于限制查询结果的行数,常用于分页查询或获取 "Top N" 数据,仅在 MySQL 中有效(SQL Server 用 TOP,PostgreSQL 用 LIMIT)。

  • 核心语法
    • 仅限制行数:SELECT 字段 FROM 表名 LIMIT 数量;(获取前 N 条记录)
    • 分页查询:SELECT 字段 FROM 表名 LIMIT 起始索引, 每页数量;(起始索引从 0 开始)
  • 示例 1(Top 5) :查询 products 表中价格最高的前 5 件商品
sql 复制代码
SELECT product_name, price FROM products 
ORDER BY price DESC 
LIMIT 5;
  • 示例 2(分页) :查询 users 表中第 2 页数据(每页 10 条,起始索引为 10)
sql 复制代码
SELECT username, age FROM users 
LIMIT 10, 10;

4. 模糊查询​:LIKE

LIKE 用于匹配字段中包含指定字符的记录,需配合通配符使用,适合 "不确定完整内容" 的查询场景(如搜索功能)。

  • 核心语法SELECT 字段 FROM 表名 WHERE 字段 LIKE '通配符表达式';
  • 常用通配符
    • %:匹配任意 0 个或多个字符(包括汉字、数字等)
    • _:匹配任意 1 个字符(仅 1 个,多一个少一个都不匹配)
  • 示例 1(包含指定字符) :查询 users 表中用户名包含 "张" 的用户
sql 复制代码
SELECT username FROM users 
WHERE username LIKE '%张%';
  • 示例 2(固定位置匹配) :查询 users 表中手机号以 "138" 开头、且第 4 位为 "0" 的用户(手机号共 11 位)
sql 复制代码
SELECT username, phone FROM users 
WHERE phone LIKE '1380_______';

5. 多表关联查询:JOIN ... ON ...

当需要从多个相关表中提取数据时(如 "订单 + 用户""商品 + 分类"),需用 JOIN 建立表间关联,核心是通过 "关联字段"(通常是外键与主键)匹配记录。

  • 常见关联类型
关联类型 作用 语法示例
INNER JOIN(内连接) 只保留两表中 "关联字段匹配" 的记录 FROM 表A INNER JOIN 表B ON 表A.字段=表B.字段
LEFT JOIN(左连接) 保留左表所有记录,右表匹配不到则补 NULL FROM 表A LEFT JOIN 表B ON 表A.字段=表B.字段
RIGHT JOIN(右连接) 保留右表所有记录,左表匹配不到则补 NULL FROM 表A RIGHT JOIN 表B ON 表A.字段=表B.字段
  • 示例 :查询 orders 表中所有订单,同时显示对应用户的用户名(orders 表的 user_id 关联 users 表的 id
  1. INNER JOIN(内连接):只保留两表中匹配条件的记录,是数据分析中最常用的关联方式。`
sql 复制代码
-- 分析每个学生的姓名、所属班级及数学成绩
SELECT 
   s.name AS 学生姓名,
   c.class_name AS 班级,
   sc.score AS 数学成绩
FROM students s
INNER JOIN classes c ON s.class_id = c.class_id  -- 学生表关联班级表
INNER JOIN scores sc ON s.id = sc.student_id     -- 关联成绩表
WHERE sc.subject = '数学';  -- 筛选数学科目
  1. LEFT JOIN(左连接) :保留左表所有记录,右表无匹配时显示 NULL,适合分析 "存在 / 缺失" 类数据(如 "未交作业的学生")。
sql 复制代码
-- 分析所有学生的英语成绩,包括缺考(成绩为NULL)的学生
SELECT 
 s.name AS 学生姓名,
 sc.score AS 英语成绩
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id AND sc.subject = '英语';
  1. RIGHT JOIN(右连接) :与左连接相反,保留右表所有记录,左表无匹配时显示 NULL,较少用(可通过交换表位置用左连接替代)。

6. 结果分组与聚合​:GROUP BY+ 聚合函数

GROUP BY 用于将表中的数据按照指定字段进行分组,相同值的记录会被归为一组;聚合函数则用于对每个分组内的数据进行计算(如求和、计数、平均值等)。

常用聚合函数:
  • COUNT():统计分组内的记录数
  • SUM():计算分组内数值的总和
  • AVG():计算分组内数值的平均值
  • MAX():获取分组内的最大值
  • MIN():获取分组内的最小值
语法示例:
sql 复制代码
-- 按性别分组,统计每组的学生人数、平均年龄
SELECT 
  gender, 
  COUNT(*) AS 人数,  -- 统计每个分组的总记录数
  AVG(TIMESTAMPDIFF(YEAR, birthdate, CURDATE())) AS 平均年龄  -- 计算平均年龄
FROM students
GROUP BY gender;  -- 按gender字段分组
注意事项:
  1. GROUP BY 后通常跟需要分组的字段名,SELECT 子句中只能出现分组字段或聚合函数,不能出现其他非分组字段。

错误示例(包含非分组字段):

sql 复制代码
SELECT gender, name, COUNT(*) FROM students GROUP BY gender;  -- 错误!name不是分组字段
  1. 可以按多个字段分组(先按第一个字段分组,同组内再按第二个字段细分):
sql 复制代码
-- 按班级和性别分组,统计每个班级中不同性别的学生人数
SELECT class_id, gender, COUNT(*) AS 人数
FROM students
GROUP BY class_id, gender;  -- 多字段分组

7. 分组后过滤​:HAVING

HAVING 用于对 GROUP BY 分组后的结果进行过滤(类似 WHERE,但 WHERE 用于分组前过滤记录,HAVING 用于分组后过滤分组)。

语法示例:
sql 复制代码
-- 按班级分组,筛选出学生人数 >= 30 的班级
SELECT 
  class_id, 
  COUNT(*) AS 班级人数
FROM students
GROUP BY class_id
HAVING 班级人数 >= 30;  -- 过滤分组结果
HAVINGWHERE 的区别:
特性 WHERE HAVING
作用时机 分组前过滤记录 分组后过滤分组
适用对象 原始表中的行 GROUP BY 后的分组
能否用聚合函数 不能(只能用字段条件) 能(常用聚合函数结果过滤)
综合示例(WHERE + GROUP BY + HAVING):
sql 复制代码
-- 1. 先筛选出2005年及以后出生的学生(WHERE)
-- 2. 按班级分组,计算每个班级的平均成绩(GROUP BY + 聚合)
-- 3. 筛选出平均成绩 >= 80 的班级(HAVING)
SELECT 
  s.class_id, 
  AVG(sc.score) AS 平均成绩
FROM students s
JOIN scores sc ON s.id = sc.student_id
WHERE YEAR(s.birthdate) >= 2005  -- 分组前过滤:只保留2005年后出生的学生
GROUP BY s.class_id  -- 按班级分组

8. 条件分支计算:CASE WHEN

当需要根据字段值动态生成分析结果时(如 "按成绩划分等级""统计不同分数段人数"),需用 CASE WHEN 实现条件逻辑。

语法示例:
sql 复制代码
-- 分析每个学生的语文成绩,并划分等级(A:90+,B:80-89,C:60-79,D:<60)
SELECT 
  s.name AS 学生姓名,
  sc.score AS 语文成绩,
  CASE 
    WHEN sc.score >= 90 THEN 'A'
    WHEN sc.score >= 80 THEN 'B'
    WHEN sc.score >= 60 THEN 'C'
    ELSE 'D'  -- 缺考或不及格
  END AS 成绩等级
FROM students s
JOIN scores sc ON s.id = sc.student_id
WHERE sc.subject = '语文';
进阶用法(结合聚合函数):
sql 复制代码
-- 统计语文成绩各等级的人数
SELECT 
  CASE 
    WHEN sc.score >= 90 THEN 'A'
    WHEN sc.score >= 80 THEN 'B'
    WHEN sc.score >= 60 THEN 'C'
    ELSE 'D'
  END AS 成绩等级,
  COUNT(*) AS 人数  -- 统计每个等级的人数
FROM scores sc
WHERE sc.subject = '语文'
GROUP BY 成绩等级;  -- 按等级分组

9. 窗口函数:OVER () 子句

窗口函数是 高级数据分析核心工具 ,可在不分组的前提下,对 "指定窗口范围" 内的数据进行计算(如 "计算每个学生在班级内的成绩排名""求每个班级的成绩平均值并关联到每条学生记录"),避免 GROUP BY 导致的结果行数减少。

常用窗口函数:
  1. 排名函数RANK()(跳跃排名)、DENSE_RANK()(连续排名)、ROW_NUMBER()(唯一序号)。
sql 复制代码
-- 分析每个班级内学生的数学成绩排名(按成绩降序)
SELECT 
 c.class_name AS 班级,
 s.name AS 学生姓名,
 sc.score AS 数学成绩,
 RANK() OVER (PARTITION BY c.class_name ORDER BY sc.score DESC) AS 班级排名
-- PARTITION BY 按班级分组(窗口范围),ORDER BY 按成绩排序
FROM students s
JOIN classes c ON s.class_id = c.class_id
JOIN scores sc ON s.id = sc.student_id
WHERE sc.subject = '数学';
  1. 聚合窗口函数SUM() OVER()AVG() OVER() 等,将聚合结果关联到每条原始记录。
sql 复制代码
-- 分析每个学生的数学成绩,及所在班级的数学平均成绩、年级平均成绩
SELECT 
  c.class_name AS 班级,
  s.name AS 学生姓名,
  sc.score AS 数学成绩,
  AVG(sc.score) OVER (PARTITION BY c.class_name) AS 班级平均分,  -- 班级窗口的平均值
  AVG(sc.score) OVER () AS 年级平均分  -- 全年级窗口的平均值(无PARTITION BY)
FROM students s
JOIN classes c ON s.class_id = c.class_id
JOIN scores sc ON s.id = sc.student_id
WHERE sc.subject = '数学';
HAVING 平均成绩 >= 80;  -- 分组后过滤:保留平均成绩≥80的班级

四、数据的增、删、改、查 (DML - 数据操作语言)

1. 插入数据​:INSERT INTO

用于向表中添加新记录,基础语法:

sql 复制代码
-- 完整语法(指定字段)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);

-- 简化语法(按表中所有字段顺序插入,需包含所有字段值)
INSERT INTO 表名 VALUES (值1, 值2, ...);

-- 批量插入
INSERT INTO 表名 (字段1, 字段2) VALUES 
  (值1, 值2),
  (值3, 值4),
  (值5, 值6);

示例 :向users表插入一条用户数据

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

2. 查询数据​:SELECT/ FROM

用于从表中获取数据,是最常用的 DML 命令,基础语法:

sql 复制代码
-- 基础查询(*表示所有字段)
SELECT 字段1, 字段2, ... FROM 表名;

-- 带条件查询
SELECT 字段 FROM 表名 WHERE 条件;

-- 排序查询(ASC升序,DESC降序,默认升序)
SELECT 字段 FROM 表名 ORDER BY 字段 排序方式;

-- 限制查询结果数量
SELECT 字段 FROM 表名 LIMIT 数量;

-- 去重查询
SELECT DISTINCT 字段 FROM 表名;

示例 :查询users表中年龄大于 18 的用户,按年龄降序排列,只显示前 5 条

sql 复制代码
SELECT username, age FROM users 
WHERE age > 18 
ORDER BY age DESC 
LIMIT 5;

3. 更新数据​:UPDATE/ SET

用于修改表中已有记录,必须加WHERE条件(否则会更新所有记录),基础语法:

sql 复制代码
UPDATE 表名 
SET 字段1 = 新值1, 字段2 = 新值2, ... 
WHERE 条件;

示例 :将users表中id=1的用户年龄改为 26

sql 复制代码
UPDATE users 
SET age = 26, email = 'new_zhangsan@example.com' 
WHERE id = 1;

注意 :无WHERE条件时会更新表中所有记录,操作前务必确认条件是否正确。

4. 删除数据​:DELETE FROM

用于删除表中记录,必须加WHERE条件(否则会删除所有记录),基础语法:

sql 复制代码
DELETE FROM 表名 WHERE 条件;

示例 :删除users表中id=5的用户

sql 复制代码
DELETE FROM users WHERE id = 5;

补充 :若需清空表中所有数据(保留表结构),可使用TRUNCATE(属于 DDL,速度更快,但无法回滚):

sql 复制代码
TRUNCATE TABLE 表名;

五、权限和事务控制 (DCL - 数据控制语言 & TCL - 事务控制语言)

DCL 主要用于控制数据库用户的访问权限,确保数据安全。核心命令包括 GRANT(授权)和 REVOKE(撤销权限)。

TCL 用于控制数据库事务,确保多步操作的原子性、一致性、隔离性和持久性(ACID 特性)。核心命令包括 START TRANSACTIONCOMMITROLLBACK

1. 创建用户并授权​:GRANT

GRANT 用于为用户分配特定权限,语法如下:

sql 复制代码
-- 创建用户并授权(MySQL 8.0 需先创建用户再授权)
CREATE USER '用户名'@'主机地址' IDENTIFIED BY '密码';

-- 授权(例如:授予对 db1 数据库所有表的查询和插入权限)
GRANT SELECT, INSERT ON db1.* TO '用户名'@'主机地址';

-- 授予所有权限(谨慎使用)
GRANT ALL PRIVILEGES ON *.* TO '用户名'@'主机地址' WITH GRANT OPTION;
  • 主机地址localhost 表示本地,% 表示所有远程主机。
  • WITH GRANT OPTION:允许用户将自己的权限授予其他用户。
  • 执行后需刷新权限:FLUSH PRIVILEGES;

2. 撤销权限​:REVOKE

REVOKE 用于收回已授予的权限,语法如下:

sql 复制代码
-- 撤销特定权限
REVOKE SELECT, INSERT ON db1.* FROM '用户名'@'主机地址';

-- 撤销所有权限
REVOKE ALL PRIVILEGES ON *.* FROM '用户名'@'主机地址';
  • 撤销后同样需要刷新权限:FLUSH PRIVILEGES;

3. 事务开始​:START TRANSACTION;BEGIN;

用于标记事务的起始点,之后的 SQL 操作将被视为一个整体:

sql 复制代码
START TRANSACTION; -- 或 BEGIN;
-- 后续的 INSERT/UPDATE/DELETE 等操作

4. 提交事务​:COMMIT;

将事务中所有操作永久保存到数据库,事务结束:

sql 复制代码
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- 两笔更新同时生效

5. 回滚事务​:ROLLBACK;

若事务中出现错误,撤销所有已执行的操作,恢复到事务开始前的状态:

sql 复制代码
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 假设此处出现错误
ROLLBACK; -- 撤销上述更新,数据回到初始状态
事务的保存点(SAVEPOINT)

复杂事务中可设置保存点,灵活回滚到指定位置:

sql 复制代码
START TRANSACTION;
UPDATE table1 SET col = 1;
SAVEPOINT sp1; -- 设置保存点
UPDATE table2 SET col = 2;
ROLLBACK TO sp1; -- 仅回滚到 sp1 之后的操作
COMMIT; -- 最终提交 table1 的更新

六、部分窗口函数

窗口函数的通用语法

所有窗口函数都遵循以下结构:

sql 复制代码
函数名([参数]) OVER (
  [PARTITION BY 分组字段]  -- 按字段划分窗口(类似GROUP BY,可选)
  [ORDER BY 排序字段 [ASC|DESC]]  -- 窗口内的排序方式(可选)
  [窗口范围]  -- 如 ROWS BETWEEN 1 PRECEDING AND CURRENT ROW(可选)
)
  • PARTITION BY:将数据划分为多个独立窗口(不写则整个表为一个窗口)。
  • ORDER BY:指定窗口内的排序规则,排名函数和偏移函数必须配合此子句使用。
  • 窗口范围:默认是从首行到当前行,可通过 ROWS/RANGE 调整(如 "前 3 行到当前行")。

应用场景

窗口函数特别适合以下分析场景:

  • 排名分析(成绩排名、销售 TOP N)
  • 同期对比(本月与上月销售额对比)
  • 累计计算(累计销售额、累计用户数)
  • 占比分析(某产品销售额占总销售额的比例)
  • 分组内的首尾值获取(班级最高分 / 最低分学生)

相比传统的 GROUP BY 聚合,窗口函数能在保留原始数据的同时附加分析结果,极大简化了复杂报表的生成逻辑。

1. 排名函数(用于生成排名序号)

  1. ROW_NUMBER()为窗口内的每条记录分配唯一的连续序号(1,2,3...),即使值相同也不会重复。

    sql 复制代码
    -- 按数学成绩降序,为每个班级的学生分配唯一排名
    SELECT 
      class_id, name, score,
      ROW_NUMBER() OVER (PARTITION BY class_id ORDER BY score DESC) AS row_num
    FROM students;
  2. RANK()生成排名时,相同值会获得相同排名,后续排名会跳过中间序号(如 1,1,3...)。

    sql 复制代码
    -- 数学成绩相同的学生排名相同,下一名次跳跃
    SELECT 
      name, score,
      RANK() OVER (ORDER BY score DESC) AS rnk
    FROM scores WHERE subject = '数学';
  3. DENSE_RANK()生成排名时,相同值获得相同排名,后续排名连续不跳跃(如 1,1,2...)。

    sql 复制代码
    -- 数学成绩相同的学生排名相同,下一名次连续
    SELECT 
      name, score,
      DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rnk
    FROM scores WHERE subject = '数学';

2. 聚合类窗口函数(对窗口数据做聚合计算)

将常见聚合函数(SUM/AVG/MAX/MIN/COUNT)用于窗口,计算每条记录所在窗口的聚合结果,且不压缩原始行数。

sql 复制代码
-- 计算每个学生的成绩及所在班级的总分、平均分
SELECT 
  class_id, name, score,
  SUM(score) OVER (PARTITION BY class_id) AS 班级总分,
  AVG(score) OVER (PARTITION BY class_id) AS 班级平均分,
  MAX(score) OVER (PARTITION BY class_id) AS 班级最高分
FROM students;

3. 分布函数(分析数据分布位置)

  1. PERCENT_RANK()计算当前行在窗口中的相对排名百分比,公式:(当前排名 - 1) / (总记录数 - 1),结果范围 [0,1]。

    sql 复制代码
    -- 计算每个学生成绩在班级内的百分比排名
    SELECT 
      class_id, name, score,
      PERCENT_RANK() OVER (PARTITION BY class_id ORDER BY score DESC) AS pct_rank
    FROM students;
  2. CUME_DIST()计算当前行及之前行的行数占窗口总记录数的比例,结果范围 (0,1],表示 "小于等于当前值的记录占比"。

    sql 复制代码
    -- 计算成绩≤当前学生的比例(如0.8表示80%的学生成绩≤当前值)
    SELECT 
      name, score,
      CUME_DIST() OVER (ORDER BY score) AS cume_dist
    FROM scores WHERE subject = '语文';

4. 偏移函数(获取相邻行数据)

用于访问窗口中当前行之前或之后的指定行数据,常用于计算 "环比""同比" 等差异。

  1. LAG(expr, n, default)获取当前行的前第 n 行数据,default 为无数据时的默认值(默认 NULL)。

    sql 复制代码
    -- 获取学生的上一次考试成绩及分数变化
    SELECT 
      name, exam_date, score,
      LAG(score, 1) OVER (PARTITION BY name ORDER BY exam_date) AS 上一次成绩,
      score - LAG(score, 1) OVER (PARTITION BY name ORDER BY exam_date) AS 分数变化
    FROM scores;
  2. LEAD(expr, n, default)获取当前行的后第 n 行数据,与 LAG 方向相反。

    sql 复制代码
    -- 获取学生的下一次考试成绩
    SELECT 
      name, exam_date, score,
      LEAD(score, 1) OVER (PARTITION BY name ORDER BY exam_date) AS 下一次成绩
    FROM scores;

5. 首尾函数(获取窗口内的首尾数据)

  1. FIRST_VALUE(expr)返回窗口内排序后的第一行数据。

    sql 复制代码
    -- 获取每个班级的第一名成绩及学生姓名
    SELECT 
      class_id, name, score,
      FIRST_VALUE(name) OVER (PARTITION BY class_id ORDER BY score DESC) AS 班级第一名
    FROM students;
  2. LAST_VALUE(expr)返回窗口内排序后的最后一行数据(注意默认窗口范围是从首行到当前行,需指定 RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 才能获取整个窗口的最后一行)。

    sql 复制代码
    -- 获取每个班级的最后一名成绩及学生姓名
    SELECT 
      class_id, name, score,
      LAST_VALUE(name) OVER (
        PARTITION BY class_id 
        ORDER BY score DESC 
        RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
      ) AS 班级最后一名
    FROM students;
相关推荐
观望过往3 小时前
非关系型数据库(NoSQL)学习指南:从入门到实战
数据库·nosql
奥尔特星云大使3 小时前
CentOS 7 上通过 RPM 包安装 Zabbix 4.x
linux·centos·zabbix
Quz3 小时前
QML TableView:基于SQLite实现增删改查
数据库·qt·sqlite
程序员勾践3 小时前
安装nginx
linux·nginx·centos
郝学胜-神的一滴4 小时前
Linux 进程控制块(PCB)解析:深入理解进程管理机制
linux·服务器·开发语言
JuneXcy4 小时前
第2章 数据库系统的核心--数据模型
数据库·mysql·oracle
CSCN新手听安4 小时前
【linux】多线程(六)生产者消费者模型,queue模拟阻塞队列的生产消费模型
linux·运维·服务器·c++
Wang's Blog4 小时前
Linux小课堂: 软件安装与源码编译实战之从 RPM 到源码构建的完整流程
linux·运维·服务器
超级大福宝4 小时前
在 Linux 下修改百度网盘的缩放比例
linux·运维·服务器·ubuntu