关系数据库标准语言(SQL)- 软考备战(三十一)

数据库系统(三)

参考资料:

数据库操作命令详解:CREATE、ALTER、DROP 的使用与实践 - 技术栈

SQL语言:DDL、DML、DQL、DCL详解 - 知乎

MySQL全面瓦解4:数据定义-DDL - 简书

【MySQL】DQL-查询语句全解 [ 基础/条件/分组/排序/分页查询 ](附带代码演示&案例练习)-腾讯云开发者社区-腾讯云

SQL------数据控制语言DCL(GRANT,REVOKE,COMMIT,ROLLBACK)_Wen先森的技术博客_51CTO博客

面试官灵魂一问: MySQL 的 delete、truncate、drop 有什么区别? - 知乎

MySQL高级篇之View视图详解,值得收藏 - 知乎


目录

数据库系统(三)

[5.3 关系数据库标准语言(SQL)](#5.3 关系数据库标准语言(SQL))

[1. 数据定义 (DDL):CREATE, ALTER, DROP](#1. 数据定义 (DDL):CREATE, ALTER, DROP)

表定义与约束

索引(底层原理与权衡)

[2. 数据查询 (DQL)](#2. 数据查询 (DQL))

完整语法与执行顺序

书写顺序

执行顺序(机器干活的顺序)

[1. )基本查询](#1. )基本查询)

[2. )条件查询](#2. )条件查询)

[3. )分组查询](#3. )分组查询)

[4. )排序查询](#4. )排序查询)

[5. )分页查询](#5. )分页查询)

[6. )连接查询(多表关联)](#6. )连接查询(多表关联))

[7. )嵌套查询(子查询)](#7. )嵌套查询(子查询))

[3. 数据操纵 (DML):INSERT, UPDATE, DELETE](#3. 数据操纵 (DML):INSERT, UPDATE, DELETE)

[4. 视图:虚拟表](#4. 视图:虚拟表)

[5. 数据控制 (DCL):GRANT, REVOKE](#5. 数据控制 (DCL):GRANT, REVOKE)


5.3 关系数据库标准语言(SQL)

之前总结的SQL语法内容链接:SQL学习文档-CSDN博客

注:SQL是非过程化语言,你只管说"要什么",不管"怎么找"。

底层找的动作由 数据模型与关系理论 - 软考备战(三十)-CSDN博客 5.2.3讲的关系代数完成。

1. 数据定义 (DDL):CREATE, ALTER, DROP

|--------------|----------|----------------------------------|
| 命令 | 核心功能 | 简要说明 |
| CREATE | 创建 | 创建新的数据库、表、视图、索引等对象。 |
| ALTER | 修改 | 修改已有对象的结构,例如添加、删除或修改字段。 |
| DROP | 删除 | 永久删除数据库对象(如表、索引),连同其数据一起删除。 |
| TRUNCATE | 清空 | 快速删除表中的所有数据,但保留表结构,通常比 DELETE 快。 |

表定义与约束

PRIMARY KEY

主键约束(唯一且不为空)。

FOREIGN KEY ... REFERENCES ...

外键约束(维护参照完整性,可加 ON DELETE CASCADE 实现级联删除)。

UNIQUE

唯一约束(允许存在一个 NULL,而主键不允许)。

NOT NULL

非空约束。

CHECK

检查约束(如 CHECK (age > 0 AND age < 150))。

索引(底层原理与权衡)

可以加速查询(相当于字典的目录),但是占用额外物理空间,降低更新速度。

(因为每次 INSERT/UPDATE/DELETE 都要动态维护索引树)

B+树具体内容链接:树和二叉树 - 软考备战(十三)-CSDN博客

底层通常使用 B+树(因为 B+树层高低,磁盘 IO 次数少,且非常适合范围查询)。

唯一索引由 UNIQUE INDEX 创建,普通索引允许重复值。

2. 数据查询 (DQL)

emp 表:id(员工ID), name(姓名), salary(薪资), age(年龄), dept_id(部门ID)

dept 表:id(部门ID), dept_name(部门名称)

|------------|----------|------------------------------------------------------------------|
| 命令 | 核心功能 | 简要说明 |
| SELECT | 查询 | 从一个或多个表中检索特定的数据列和行,可结合 WHERE、GROUP BY、HAVING、ORDER BY 等子句进行复杂查询。 |

完整语法与执行顺序
书写顺序

SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY

执行顺序(机器干活的顺序)

FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

口诀

先找表,再过滤,后分组,组过滤,挑列,最后排序

F W G H O S (From -> Where -> Group -> Having -> Order -> Select(提取) -> Limit

1. )基本查询

最简单的数据检索,包含去重、算术运算、别名等。

|----------------------|------------|---------------------------------------------------|
| 语法 / 关键字 | 作用 | 示例 |
| SELECT ... | 查询指定列 | SELECT name, salary FROM emp; |
| * | 查询所有列 | SELECT * FROM emp; |
| DISTINCT | 去除重复记录 | SELECT DISTINCT dept_id FROM emp; |
| AS | 起别名(AS可省略) | SELECT name AS '姓名', salary*12 AS '年薪' FROM emp; |

2. )条件查询

使用 WHERE 子句过滤符合条件的数据。

|----------|-----------------------|---------------------------------------------------------|
| 分类 | 关键字 / 运算符 | 示例 |
| 逻辑运算 | AND OR NOT | SELECT * FROM emp WHERE age > 25 AND salary < 10000; |
| 范围查询 | BETWEEN...AND... | SELECT * FROM emp WHERE salary BETWEEN 5000 AND 10000; |
| 集合查询 | IN(...) NOT IN(...) | SELECT * FROM emp WHERE dept_id IN (10, 20, 30); |
| 模糊查询 | LIKE ( %任意多字符, _单个字符) | SELECT * FROM emp WHERE name LIKE '张%'; (查张姓) |
| 空值判断 | IS NULL IS NOT NULL | SELECT * FROM emp WHERE dept_id IS NOT NULL; |

3. )分组查询

将数据按某个列分组,配合聚合函数进行统计分析。

|----------------------|-----------------------------------------------|-----------------------------------------------------------------------------|
| 关键字 / 函数 | 作用 | 示例 |
| GROUP BY | 按列分组 | SELECT dept_id FROM emp GROUP BY dept_id; |
| 聚合函数 | COUNT()计数, SUM()求和, AVG()平均, MAX()最大, MIN()最小 | SELECT dept_id, COUNT(*), AVG(salary) FROM emp GROUP BY dept_id; |
| HAVING | 分组后 过滤(不能用WHERE) | SELECT dept_id, COUNT(*) AS cnt FROM emp GROUP BY dept_id HAVING cnt > 5; |

WHERE vs HAVING 区别

WHERE 在分组前过滤,不能使用聚合函数。

HAVING 在分组后过滤,专门配合聚合函数使用。

GROUP BY 的潜规则

当使用 GROUP BY 时,SELECT 后面只能出现分组列和聚合函数(如 COUNT, SUM, AVG),绝不能出现其他独立的列。

4. )排序查询

将查询结果按指定列进行升序或降序排列。

|----------------------|----------------|-------------------------------------------------------|
| 语法 / 关键字 | 作用 | 示例 |
| ORDER BY | 指定排序的列 | SELECT * FROM emp ORDER BY salary; |
| ASC | 升序(默认值,可省略) | SELECT * FROM emp ORDER BY salary ASC; |
| DESC | 降序 | SELECT * FROM emp ORDER BY salary DESC; |
| 多列排序 | 按第一列排,相同则按第二列排 | SELECT * FROM emp ORDER BY dept_id ASC, salary DESC; |

5. )分页查询

物理上将数据分段返回,避免一次性加载过多数据导致内存溢出(常用于前端表格翻页)。

|----------------|-----------------------------------------------|---------------------------------------------------------------------------------------|
| 数据库 | 语法公式 | 示例(查询第 2 页,每页 5 条) |
| MySQL | LIMIT 偏移量, 每页条数 *(公式:LIMIT (页码-1)*条数, 条数)* | SELECT * FROM emp LIMIT 5, 5; |
| Oracle | ROWNUM 伪列 | SELECT * FROM (SELECT a.*, ROWNUM rn FROM emp a WHERE ROWNUM <= 10) WHERE rn > 5; |
| SQL Server | OFFSET...FETCH | SELECT * FROM emp ORDER BY id OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY; |

注意: 不同数据库的分页语法不通用。

6. )连接查询(多表关联)

当需要的数据分散在多张表中时,通过主外键关系将表拼接到一起。

假设:emp.dept_id 关联 dept.id

|----------|-----------------------|------------------------|----------------------------------------------------------------------------------------------|
| 连接类型 | 关键字 | 作用描述 | 示例 |
| 内连接 | INNER JOIN ... ON ... | 只返回两表中能匹配上的交集数据 | SELECT e.name, d.dept_name FROM emp e INNER JOIN dept d ON e.dept_id = d.id; |
| 左外连接 | LEFT JOIN ... ON ... | 返回左表全部数据,右表匹配不上的补 NULL | SELECT e.name, d.dept_name FROM emp e LEFT JOIN dept d ON e.dept_id = d.id; (能查出没有部门的员工) |
| 右外连接 | RIGHT JOIN ... ON ... | 返回右表全部数据,左表匹配不上的补 NULL | SELECT e.name, d.dept_name FROM emp e RIGHT JOIN dept d ON e.dept_id = d.id; (能查出没有任何员工的空部门) |

推荐写法:

使用上述的 JOIN ... ON ... 标准语法,淘汰老式的 SELECT * FROM emp, dept WHERE emp.dept_id = dept.id

(容易漏写条件导致笛卡尔积)

7. )嵌套查询(子查询)

一个查询(内查询)的结果,作为另一个查询(外查询)的条件。

常用于解决复杂的逻辑判断。

|-----------------------|-------------------------|---------------------------------------------------------------------------------------------------------|
| 分类 | 特点 | 示例 |
| WHERE 后的标量子查询 | 内查询返回单个值(一行一列) | SELECT * FROM emp WHERE salary = (SELECT MAX(salary) FROM emp); (查工资最高的人) |
| WHERE 后的列子查询 | 内查询返回一列多行,需用 IN | SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE dept_name = '研发部' OR dept_name = '产品部'); |
| FROM 后的表子查询 | 内查询返回多行多列,当作一张临时表使用 | SELECT * FROM (SELECT name, salary FROM emp WHERE age > 25) AS temp WHERE temp.salary > 8000; |

在实际开发中,子查询虽然逻辑直观,但往往可以被改写为 连接查询(JOIN),大多数情况下 JOIN 的执行效率优于子查询。

IN

等于子查询返回的集合中的任意一个值。

(适合外表大,内表小的情况)

ANY / ALL

与子查询返回的每一个值比较。

>ANY(大于最小即可),>ALL(大于最大才行)。

EXISTS

不返回具体数据,只返回逻辑 True/False。

-执行机制:

外表驱动内表。外表逐行代入内表,只要内表能查到结果,外层就保留这一行。

-效率对比:

如果外表小、内表大,用 EXISTS 效率远高于 IN(因为 IN 会先把内表全部查出来构建一个大集合)。

3. 数据操纵 (DML):INSERT, UPDATE, DELETE

|------------|----------|------------------------------|
| 命令 | 核心功能 | 简要说明 |
| INSERT | 插入 | 向表中插入新的数据记录。 |
| UPDATE | 更新 | 修改表中已有的数据记录。 |
| DELETE | 删除 | 删除表中的数据记录,可以配合 WHERE 条件精确删除。 |

基本语法

INSERT INTO 表名(列名) VALUES (值)

一次插入一行。

UPDATE 表名 SET 列名=值 WHERE 条件

千万别漏掉 WHERE,否则全表更新!

DELETE FROM 表名 WHERE 条件

千万别漏掉 WHERE,否则全表删除!

DELETE vs TRUNCATE
DELETE

属于 DML 语句。

按行删除,速度慢。

删除的数据可以回滚。

不会重置自增列(AUTO_INCREMENT)的计数器。

会触发触发器。

TRUNCATE TABLE

属于 DDL 语句。

快速清空整张表(直接释放数据页,不逐行删)。

无法回滚。

会重置自增计数器归零。不会触发触发器。

4. 视图:虚拟表

本质

只存查询定义(SQL逻辑),不存实际数据。

每次查视图,底层都是去执行一遍对应的 SQL 查询原表。

作用
数据安全

屏蔽敏感列(如:创建一个不含工资列的员工视图给外部查询)。

简化复杂查询

把复杂的多表连接做成视图,以后直接 SELECT FROM 视图。

视图的更新限制

当视图中的数据发生变化时,数据表中的数据也会发生变化,反之亦然。

并非所有视图都能执行 INSERT/UPDATE/DELETE。

以下视图不可更新(只能查,不能改):

  1. 包含聚合函数(如 SUM, COUNT)或 GROUP BY 的视图。
  2. 包含 DISTINCT 的视图。
  3. 包含多表连接(JOIN)的视图。
视图列

由表达式或常量计算得出的(如 SELECT age2 FROM ...)。

WHERE 子句中引用了被查表的列(如 WHERE id IN (SELECT id FROM 本表))。

5. 数据控制 (DCL):GRANT, REVOKE

|------------|----------|------------------------------------|
| 命令 | 核心功能 | 简要说明 |
| GRANT | 授予权限 | 将特定的权限(如 SELECT, INSERT)授予某个用户或角色。 |
| REVOKE | 撤销权限 | 取消之前授予某个用户或角色的权限。 |

授权
语法

GRANT 权限(如 SELECT, UPDATE) ON 对象(如表名/视图名) TO 用户 [WITH GRANT OPTION];

重点

带 [WITH GRANT OPTION] 表示该用户不仅拥有了权限,还获得了"转授权"的资格,可以把这个权限再发给其他用户。

收权
语法

REVOKE 权限 ON 对象 FROM 用户;

级联收回

如果用户 A 把权限发给了 B(带了选项),A 又发给了 C。

此时 DBA 撤销 A 的权限,必须使用 CASCADE 关键字,这会导致 B 和 C 的权限也被连锁收回。

收回权限默认只收直接发给你的,带上 CASCADE 才能"拔出萝卜带出泥"。

相关推荐
2402_854808372 小时前
html如何修改备注
jvm·数据库·python
xier_ran2 小时前
【C++】static 关键字与 const 关键字的作用
java·数据库·microsoft
2401_835956812 小时前
Tailwind CSS如何实现文字装饰线_使用decoration系列类丰富CSS文字
jvm·数据库·python
qq_334563552 小时前
如何在MongoDB中实现连表查询_group与累计求和操作
jvm·数据库·python
木泽八2 小时前
分布式系统架构模式精讲:CQRS、Saga与数据库选型完全指南
数据库·架构
weixin_580614002 小时前
C#怎么模拟键盘按键输入_C#如何实现自动化脚本【教程】
jvm·数据库·python
橙露2 小时前
Redis 缓存穿透、击穿、雪崩解决方案
数据库·redis·缓存
山峰哥2 小时前
解锁SQL优化新境界:从索引策略到高效查询实战
数据库·sql·oracle
云烟成雨TD2 小时前
Spring AI Alibaba 1.x 系列【24】结构化输出(Structured Output)
数据库·人工智能·spring