5-2. SQL
一、嵌入式查询(子查询):父查询的“数据来源”
子查询是嵌套在另一个SQL语句(父查询)中的查询,核心作用是为父查询提供过滤条件或数据输入。它的关键区别在于“是否依赖父查询数据”,可分为两类。
1. 子查询的核心分类
| 类型 | 定义 | 执行顺序 | 典型场景 |
|---|---|---|---|
| 非相关子查询 | 子查询不使用父查询中的任何字段,可独立执行 | 先执行子查询,再将结果传给父查询 | 用IN判断“是否在子查询结果中” |
| 相关子查询 | 子查询依赖父查询的字段(如你笔记中的s.sno),无法独立执行 | 类似“for循环”:父查询每读一行,子查询就执行一次 | 用EXISTS判断“父查询行是否存在匹配的子查询结果” |
2. 子查询常用运算符:IN / ALL / ANY / EXISTS
这四个运算符是子查询与父查询的“连接桥梁”,用法和场景差异很大,必须区分清楚。
-
IN:判断父查询字段是否“存在于子查询的结果集中”(只要有一个匹配就满足)
示例:查询选过“c002”课程的学生姓名(非相关子查询写法)
-
ALL:判断父查询字段是否“满足子查询结果集中的所有条件”(需搭配比较运算符,如>、<)
示例:查询“所有课程成绩都大于80分”的学生姓名
-
ANY:判断父查询字段是否“满足子查询结果集中的任一条件”(同样搭配比较运算符)
示例:查询“至少有一门课程成绩大于90分”的学生姓名
-
EXISTS:判断“子查询是否能返回结果”(只要子查询有1行结果,就返回true,效率比IN高)
对应你笔记中的例子(相关子查询经典场景):
✅ 注意:select Sname from student s -- 父查询:遍历每一个学生s where exists( -- 子查询:判断当前学生s是否有选c002的记录 select sc.sno from sc where sc.sno = s.sno -- 子查询依赖父查询的s.sno and sc.cno = 'c002' );EXISTS只关心子查询“有没有结果”,不关心结果是什么,所以子查询字段写*也可以(如select * from sc...)。
二、视图(View):虚拟的“结果表”
视图不是真实的表(不存储数据),而是由一个查询语句定义的“虚拟表”。它的核心价值是简化查询、控制数据访问权限,避免直接操作原始表。
1. 视图的核心作用
- 简化复杂查询:将多表关联、聚合计算的复杂SQL封装成视图,后续查询直接用视图名即可。
- 权限控制:只给用户开放视图的访问权限(如只能看部分字段),保护原始表的敏感数据(如学生的身份证号)。
- 数据独立性:即使原始表结构变化,只要视图的查询逻辑调整,依赖视图的程序无需修改。
2. 视图的基本操作:创建、查询、更新、删除
-
创建视图(对应你笔记的语法,补充完整示例):
示例:创建“计算机系男生”的视图,只显示学号、姓名、年龄
-
查询视图(和查普通表完全一样):
-
更新视图(有严格限制,不是所有视图都能更新):
❌ 不可更新的情况:视图含聚合函数(如
✅ 可更新的情况:视图由单表查询定义,无DISTINCT、聚合函数(如COUNT)、GROUP BY等。
示例:修改视图中某学生的年龄
create view grade_avg as select sno, avg(grade) from sc group by sno),因为无法反向修改“平均值”对应的原始成绩。 -
删除视图(只删除视图定义,不影响原始表数据):
3. 视图的权限控制
通过GRANT语句给不同用户分配视图的操作权限,实现“数据隔离”。
示例:给用户“user1”分配“查询M_student视图”的权限,但禁止修改:
三、SQL约束:保证数据的“正确性和完整性”
约束是对表中数据的规则限制,防止插入无效、错误的数据。你提到了“外键”,这里补充所有常用约束类型,形成完整体系。
1. 常见约束类型
| 约束名称 | 关键字 | 作用 | 示例(创建student表时添加) |
|---|---|---|---|
| 非空约束 | NOT NULL | 字段值不能为NULL(如学生姓名不能为空) | Sname varchar(20) NOT NULL |
| 唯一约束 | UNIQUE | 字段值在表中唯一(如学号不能重复,可允许NULL) | sno varchar(10) UNIQUE |
| 主键约束 | PRIMARY KEY | 非空+唯一,唯一标识表中每一行(如学号) | sno varchar(10) PRIMARY KEY |
| 外键约束 | FOREIGN KEY | 关联两张表,保证“参照完整性”(如sc表的sno关联student表的sno) | 见下文详细示例 |
| 检查约束 | CHECK | 限制字段值的范围(如年龄不能小于0) | Sage int CHECK (Sage > 0) |
2. 外键约束
外键是“子表”中引用“父表”主键的字段,用来保证两张表的数据逻辑一致(比如“选课记录”的学生,必须是“学生表”中存在的学生)。
-
语法示例(创建sc表时,用sno关联student表的sno):
-
核心作用:
- 防止插入无效数据:比如往sc表插入一个不存在的学号(如“2023999”),会报错。
- 防止删除被引用的数据:若不设置
ON DELETE CASCADE,直接删除student表中已选课的学号,会报错。