数据库作战记录2

【4.1】★★☆☆☆

考点:在串联的自然连接(NATURAL JOIN)中,在"字段被'用掉'一次后,就无法再用于后续连接"的风险。

NATURAL JOIN 无法区分"用于连接本表的字段"和"用于连接下一张表的字段"。当 section 表被加入时,它的 course_id 已经被用来和 teaches 表的 course_id 对齐了。当你试图用这个结果再去 NATURAL JOIN course 时,数据库会尝试匹配所有同名字段

section 表和 course 表同名的字段只有 course_id
teaches 表和 course 表同名的字段也只有 course_id

此时生成的中间结果集 里,虽然保留了 course_id,但这个 course_id 已经不再是"属于 section 表的原始字段"了,它是一个合并后的字段。

【4.2】

【a题】★☆☆☆☆

考点:COALESCE(a.name, b.name)的使用

涉及表格:instructor teaches

提示:

COALESCE(T.sect_id, 0) 是一个SQL函数,

使用 COALESCE(a.name, b.name) AS name 的意思是:

"请优先看 a.name,如果它不是 NULL ,就用它;如果它是 NULL,那就退而求其次用 b.name。"

具体含义是:检查 T.sect_id 这个字段的值。

  • 如果 T.sect_id 不是 NULL ,就返回 T.sect_id 本身的值。
  • 如果 T.sect_id NULL ,就返回 0

最终,这个表达式的结果会被命名为 SectionID

这个函数常用于为可能为空的字段提供一个"兜底"的默认值,确保查询结果中不会出现 NULL,从而使数据更清晰,或避免在后续计算中出现问题。

显示所有教师,因此instructor英国作为主表,左联,从表选用teaches,然后用coalesce teaches的sect_id字段,并设置替换值为0

【正解】

select instructor.ID coalesce(teaches.ID, 0) AS SECTION_ID

from instructor left outer join teaches on instructor.ID=teaches.ID

【b题】☆☆☆☆☆

标量子查询本质上就是一个只返回单个值(一行一列)的子查询。你可以把它想象成一个"临时变量"或者一个"动态计算出的数值",因为它返回的结果是单一的

【正解】

select instructor.ID coalesce(teaches.ID, 0) AS SECTION_ID from instructor, teaches where instructor.ID=teaches.ID

【c题】★★★☆☆

考点:join的顺序

涉及表:teaches instructor

思路:明确指出要写出有多少位老师就有多少记录,因此instructor作为主表,section作为从表

select section.sec_id, instructor.ID, coalesce(teaches.ID, "-") AS instructor_name

from instructor left outer join teaches on instructor.ID=teaches.ID left outer join section on section.course_id=teaches.course_id

where teaches.year=2018 and teaches.semester="Spring"

先写 Instructor I 会导致结果不符合题目 c 的要求 ,主要有两个核心问题:会漏掉没老师的课程 ,并且结果集的主体变成了"老师"而不是"课程段"

题目 c 的核心要求是:"显示 2018 年春季开设的所有课程段的列表"

  • 你的写法 :以 Instructor(老师)为主表。这意味着 SQL 会先找所有老师,然后看他们教了什么课。
  • 后果 :如果某门课(Section)还没有安排任何老师 ,那么 Instructor 表里就没有对应的人,这门课就不会出现在结果的第一行。这直接违反了题目"没老师的课程也要显示"的要求。

【正解】

select section.sec_id, instructor.ID, coalesce(teaches.ID, "-") AS instructor_name

from section left outer join teaches on ( section.course_id=teaches.course_id and section.sec_id=teaches.sec_id ) left outer join instructor on instructor.ID=teaches.ID

where teaches.year=2018 and teaches.semester="Spring"

在你提供的 SQL 语句中,"有多少位老师就有多少记录"这一逻辑的实现,核心在于 表之间的连接方式 以及 主表的选择。我们来逐步分析它是如何运作的:

1. 主表是 Section(课程段)

复制代码
1FROM Section S

这是整个查询的"地基"。这意味着最终的结果集首先会包含所有满足 WHERE 条件的课程段。即使某个课程段暂时没有老师,它也会先被选出来。

2. 第一次连接:LEFT OUTER JOIN Teaches

复制代码
1LEFT OUTER JOIN Teaches T ON (S.CourseID = T.CourseID AND S.SecID = T.SecID)
  • 作用 :将课程段(Section)与排课记录(Teaches)关联起来。
  • 关键点Teaches 表通常是一对多的关系。一门课(Section)可以对应 Teaches 表中的多条记录,每条记录代表一位老师。
  • 效果 :如果课程段 A 有 3 位老师,那么在 Teaches 表里就会有 3 条关于课程段 A 的记录(CourseIDSecID 相同,但 ID 不同)。当 SectionTeaches 连接时,这 3 条记录会被"展开",导致课程段 A 在结果中出现 3 次。

3. 第二次连接:LEFT OUTER JOIN Instructor

复制代码
1LEFT OUTER JOIN Instructor I ON T.ID = I.ID
  • 作用 :根据 Teaches 表里的老师 ID,去查找老师的具体信息(如姓名)。
  • 效果:由于上一步已经把"一个课程段对应多位老师"的情况展开成了多行,这一步只是给每一行配上具体的老师名字。

总结

这个查询之所以能实现"有多少位老师就有多少记录",是因为它利用了 Teaches 表作为中间桥梁

【d题】

涉及表:instructor department

将instructor按dept_namegroupby,然后select的时候count一下id。这里要保证没有教师的系也要显示,因此外左联系,系做主表,教师做从表

【正解】

select D.name count(I.ID) AS faculty

from department D left outer join instructor I on D.dept_name=I.dept_name

group by D.dept_name

【4.7】☆☆☆☆☆

主键,主键非空,外域键约束

CREATE TABLE employee(

ID varchar2(5) PRIMARY KEY not null,

person_name varchar2(5) not null,

street varchar2(10),

city varchar2(10)

)

CREATE TABLE company(

company_name varchar2(5) PRIMARY KEY not null,

city varchar2(10),

)

CREATE TABlE manages(

ID varchar2(5) PRIMARY KEY not null,

manager_id varchar2(10)

FOREIGN KEY(ID) references employee(ID)

FOREIGN KEY(manager_id) references employee(ID)

)

CREATE TABLE works(

ID varchar(5) PRIMARY KEY not null,

company_name varchar2(5),

salary numeric(10,2),

FOREIGN KEY(company_name) references company(company_name)

FOREIGN KEY(ID) references employee(ID)

)

【4.10】★★☆☆☆

考点:COALESCE(a.name, b.name) 带ON的全外联与自然全外联的区别 合并拷贝表

使用 COALESCE(a.name, b.name) AS name 的意思是:

"请优先看 a.name,如果它不是 NULL ,就用它;如果它是 NULL,那就退而求其次用 b.name。"

语法 连接类型 连接条件指定方式 适用场景
Natural Join 内连接(默认)或外连接 自动匹配所有同名列 两表有完全同名的列,且需自动连接时
ON 所有连接类型(内、外、交叉) 显式指定任意条件(不限于同名列) 需灵活控制连接条件(如非同名列、复杂逻辑)
USING 所有连接类型(内、外、交叉) 显式指定同名列 两表有完全同名的列,需显式声明连接条件时

要理解自然全外连接(NATURAL FULL OUTER JOINON 条件的全外连接(FULL OUTER JOIN ... ON 的区别,需从连接条件的指定方式结果列的处理适用场景 等维度分析。结合你给出的关系 a(name, address, title)b(name, address, salary),我们通过定义、语法、结果列、连接条件四个角度对比:

定义与连接条件

  • 自然全外连接 :自动以两表所有同名属性 作为连接条件,匹配这些属性值相等的元组,同时保留两表中未匹配的元组。

    对于 ab,同名属性是 nameaddress,因此连接条件是 a.name = b.name AND a.address = b.address

    语法:a NATURAL FULL OUTER JOIN b(无需显式写条件,自动识别同名属性)。

  • ON 的全外连接 :需显式指定连接条件 (可以是任意条件,不限于同名属性),匹配条件成立的元组,同时保留未匹配的元组。

    语法:a FULL OUTER JOIN b ON (a.name = b.name AND a.address = b.address)(需手动写条件)。

结果列的处理

  • 自然全外连接 :结果中同名属性只保留一份 (自动合并),无重复列。

    例如:ab 都有 nameaddress,结果中只显示 nameaddress 各一列,再合并 a.titleb.salary,最终列:name, address, title, salary

  • ON 的全外连接 :结果中同名属性会保留两份 (来自 ab 各一列),需通过 COALESCE 等函数合并(否则会有 a.nameb.name 等重复列)。

空值处理与合并

  • 自然全外连接 :自动处理同名属性的空值,合并后同名属性只有一列(本质是隐式合并)。

    例如:若 a 中某元组 name 为空,b 中某元组 name 为空,自然连接会将这两个空值视为"匹配"(空值与空值相等?不,SQL 中 NULL = NULLUNKNOWN,但自然连接的实现通常会将空值视为可匹配,或通过数据库实现逻辑处理)。

  • ON 的全外连接 :需手动合并同名属性 (如用 COALESCE(a.name, b.name)),否则结果会有重复列。同时,空值的匹配逻辑由 ON 条件决定(如 a.name = b.name 中,NULL = NULLUNKNOWN,但全外连接会保留未匹配行,因此空值行会被保留)。

【正解】

select coalesce(a.name, b.name) AS name, coalesce(a.address,b,address) AS address, title, salary

from a full outer join b on (a.name=b.name and a.address=b.address)

维度 自然全外连接 (NATURAL FULL OUTER JOIN) ON 的全外连接 (FULL OUTER JOIN ... ON)
连接条件 自动以所有同名属性为条件 需显式指定条件(可任意)
结果列 同名属性自动合并为1列 同名属性保留2列(需手动合并)
空值处理 隐式合并,自动处理同名属性空值 需手动合并(如 COALESCE),空值匹配由 ON 条件决定
语法灵活性 依赖同名属性,结构变化需修改 灵活,可指定任意条件,但需手动处理重复列

【4.12】★☆☆☆☆

考点:权限追溯 权限依赖传递 权限归属权职绑定

核心作用是明确权限授予的"责任主体"与"上下文",尤其在涉及角色权限传递、审计追踪、权限隔离等场景中至关重要。是否包含该子句,取决于用户希望如何管理权限的"来源"与"可追溯性"。

在数据库权限体系中,权限可以由用户直接拥有 ,也可以通过角色继承获得。当一个用户(或角色)将权限授予另一个用户时,系统需要记录"是谁(或哪个角色)授出的权限",以便在权限回收、审计、角色失效时能精准追溯和控制。

为什么"应该"包含 GRANTED BY CURRENT ROLE

当授权行为是通过角色完成时,包含该子句有以下关键价值:

  1. 权限来源可追溯

    数据库系统(如 Oracle、PostgreSQL)会记录权限的"授予者"。若使用角色授权,GRANTED BY CURRENT ROLE 明确指出该权限是由当前激活的角色授出的,而非用户本身。这在审计日志、权限合规检查中至关重要。

  2. 支持角色权限的"传递性"与"隔离性"

    如果一个角色 A 被授予了 SELECT 权限,并通过 GRANT ... GRANTED BY A 授予用户 B,那么当角色 A 被撤销时,系统可以自动识别并处理通过 A 授出的权限(如级联撤销或标记为"孤儿权限"),避免权限"悬空"或滥用。

  3. 避免权限"污染"与"混淆"

    若不指定 GRANTED BY,系统可能默认将权限归因于执行授权的"当前用户",而非其扮演的角色。这会导致权限归属混乱------例如,用户以角色 A 登录并授权,但权限却显示为"用户本人"授出,未来角色 A 被撤销时,该权限可能不会被自动清理,造成安全风险。

  4. 符合最小权限原则与职责分离

    在企业级系统中,权限管理常遵循"角色驱动"模式。通过显式指定 GRANTED BY CURRENT ROLE,可以确保权限的授予行为与角色的职责绑定,避免用户以"个人身份"越权授出本应由角色管理的权限。

【4.13】

考点:权限依赖

【1题】★☆☆☆☆

不一定需要,v依赖于r,相对于视图只能是r的列子集,不需要看到全貌,比如管理系统表r有很多信息包括教师的工资,但教务处是不能看到工资的,这张对教务处的表格v就是引用自全表r的,那么让教务处查看v表,不需要让教务处拥有查看r表的权限。

【2题】★☆☆☆☆

需要,因为v是依赖于r的,修改v必然会引发对r的修改。

【3题】★☆☆☆☆

假设教务处录入新老师,新老师的年龄是33岁,但是视图v的筛选条件有where age<30,那么INSERT INTO v (id, name, age) VALUES (1, 'Wang', 33); 会显示插入成功,但是受限于视图条件,并不会被展示出来。

相关推荐
无名-CODING2 小时前
Docker 部署 Redis:小白一键安装、配置与迁移教程
数据库·redis·bootstrap
IMPYLH2 小时前
Linux 的 env 命令
linux·运维·服务器·数据库
fobwebs2 小时前
如何通过phpmyadmin指令来优化数据库表,给数据库“减肥”。
数据库·wordpress·数据库优化·phpmyadmin
syinfo2 小时前
oracle使用PLSQL导出表数据
数据库·oracle
客梦2 小时前
数据库基础
数据库·笔记
老苏畅谈运维2 小时前
Oracle AI Database 26ai 安装实战
数据库·oracle·oracle 26ai
Rick19932 小时前
SQL优化
数据库·sql
沪漂阿龙2 小时前
掌握MySQL这些函数,SQL水平直接起飞!
数据库·sql·mysql
无忧智库3 小时前
破局与重构:基于“智慧大脑”的企业全面数据化经营深度解构(PPT)
数据库·重构