概念整理 码 来自这篇博客 。
超码 一个或多个属性的集合,其中可能包含冗余属性 可在一个关系中唯一标识一个元组 候选码 主码 候选码中选出的唯一标识符 不能为 NULL
,且值唯一 外码 本关系/表中的某个属性恰好是另外一个关系里的主码 建立表间关系 名称 定义 说明 超码 能唯一标识元组的属性集合 可以是多个字段组成 候选码 最小的超码 ,不能去掉字段可能有多个 主码 从候选码中选出的“主键” 唯一、非空、不变 外码 指向另一个关系主码的属性 用于建立表与表之间的联系
graph TD
A[超码] -->|"最小集合,可以有多个"| B[候选码]
B -->|"从不同的候选码中选出一个"| C[主码]
D[外码] -. "是另一个表的主码" .-> C
B --> F["其他候选码"]
题目整理 第一题 已知关系模式 R ⟨ U , F ⟩ R\langle U, F\rangle R ⟨ U , F ⟩ ,有 U = { A , B , C , D , E , F } U=\{A, B, C, D, E, F\} U = { A , B , C , D , E , F } 和 F = { A → B C D , B C → D E , B → D , D → A } F=\{A\to BCD, BC\to DE, B\to D, D\to A\} F = { A → BC D , BC → D E , B → D , D → A } 。
证明 D F DF D F 是一个候选码。
写出所有候选码。
证明 :
候选码的定义是能唯一标识元组的最小属性集,它闭包包含所有属性 ,即 D F + = U {DF}^+ = U D F + = U ,证明如下:初始:D F + = { D , F } {DF}^+ = \{D, F\} D F + = { D , F } 依赖:D → A D \to A D → A ,加上 A A A A → B C D A \to BCD A → BC D ,加上 B B B , C C C 此时 D F + = { A , B , C , D , F } {DF}^+ = \{A, B, C, D, F\} D F + = { A , B , C , D , F } B C → D E BC \to DE BC → D E ,我们已经有 B B B , C C C ,所以加上 E E E 最后 D F + = { A , B , C , D , E , F } = U {DF}^+ = \{A, B, C, D, E, F\} = U D F + = { A , B , C , D , E , F } = U 解 :
首先, D D D 、 F F F 不是候选码。显然。 枚举是个技术活,指数复杂度,观察得到只有 D F DF D F 一个候选码。 第二题 图书馆欲开发一套管理系统,数据库需要保存以下信息:
其中,一个学生可以借 0 ~ 5 本书,借书过程需要记录起止时间,书库中可以存放图书,需要记录存放的每一种书的数量,一名管理员负责管理一个书库。
完成以下设计:
设计该系统的 E-R 图。 将 E-R 图转换为关系模式。 指出转换后,每个关系模式的主码。 E-R 图如下:
erDiagram
Book ||--o{ Store : "stored in"
Book {
string BookID
string Title
float Price
string Author
}
Library ||--o{ Store : "has"
Library ||--|| Admin : "managed by"
Library {
string LibraryID
string Location
float Area
string Phone
}
Admin {
string AdminID
string Name
string Gender
string Position
}
Student ||--o{ Borrow : "borrows"
Student {
string StudentID
string Name
string Gender
int Age
string Department
}
Borrow {
date StartDate
date EndDate
}
Book ||--|| Borrow : "borrowed"
Store {
int Quantity
}
关系模式如下,主码加粗:
Book(BookID , Title, Price, Author) Library(LibraryID , Location, Area, Phone) Admin(AdminID , Name, Gender, Position) Student(StudentID , Name, Gender, Age, Department) Store(LibraryID , BookID , Quantity) ,多对多,联合主码 Borrow(StudentID , BookID , StartDate, EndDate) ,多对多,联合主码 Manages(LibraryID , AdminID) ,一对一,用联合主码表示,或任选其一为主码 第三题 根据下列关系模式:
department(dept_name, building, budget)
instructor(ID, name, dept_name, salary)
course(course_id, title, dept_name, credits)
section(course_id, sec_id, semester, year, building, room_number, time_slot_id)
teachers(ID, course_id, section_id, semester, year)
student(ID, name, dept_name, tot_cred)
prereq(course_id, prereq_id)
advisor(s_id, i_id)
takes(id, course_id, sec_id, semester, year, grade)
classroom(building, room_number, capacity)
time_slot(time_slot_id, day, start_time, end_time)
用关系代数和 SQL 语句完成下列查询操作:
查询 2020 年秋季未选课的学生的 ID 查询选了名为 'Einstein'
的老师开设的所有课程的学生的姓名(老师、学生不存在重名的) 查询所有在 2020 年秋季开课且不在 2021 年春季开课的课程 ID 给年薪大于 70000 元的老师涨 5% 工资,小于等于这个数字的老师涨 10% 不用聚合函数,查询老师的最高工资 第一问 :
π ID ( student ) − π ID ( σ semester=’Fall’ ∧ year = 2020 ( takes ) ) \pi_\text{ID}(\text{student}) - \pi_\text{ID}(\sigma_{\text{semester='Fall'} \land \text{year}=2020}(\text{takes})) π ID ( student ) − π ID ( σ semester=’Fall’ ∧ year = 2020 ( takes ))
1 2 3 4 5 6 7 SELECT IDFROM studentWHERE ID NOT IN ( SELECT id FROM takes WHERE semester = 'Fall' AND year = 2020 );
第二问 :
π student.name ( student ⋈ student.ID = takes.id takes ⋈ takes.course_id = teachers.course_id ∧ takes.section_id = teachers.section_id ∧ takes.semester = teachers.semester ∧ takes.year = teachers.year teachers ⋈ teachers.ID = instructor.ID σ instructor.name = ’Einstein’ ( instructor ) ) \pi_\text{student.name} \left( \text{student} \bowtie_\text{student.ID = takes.id} \text{takes} \bowtie_{\text{takes.course\_id = teachers.course\_id} \land \text{takes.section\_id = teachers.section\_id} \land \text{takes.semester = teachers.semester} \land \text{takes.year = teachers.year}} \text{teachers} \bowtie_\text{teachers.ID = instructor.ID} \sigma_\text{instructor.name = 'Einstein'}(\text{instructor}) \right) π student.name ( student ⋈ student.ID = takes.id takes ⋈ takes.course_id = teachers.course_id ∧ takes.section_id = teachers.section_id ∧ takes.semester = teachers.semester ∧ takes.year = teachers.year teachers ⋈ teachers.ID = instructor.ID σ instructor.name = ’Einstein’ ( instructor ) )
1 2 3 4 5 6 7 8 9 SELECT student.nameFROM studentJOIN takes ON student.ID = takes.idJOIN teachers ON takes.course_id = teachers.course_id AND takes.section_id = teachers.section_id AND takes.semester = teachers.semester AND takes.year = teachers.yearJOIN instructor ON teachers.ID = instructor.IDWHERE instructor.name = 'Einstein' ;
(也可以使用 ÷ \div ÷ 运算)
第三问 :
π course_id ( σ semester=’Fall’ ∧ year=2020 ( section ) ) − π course_id ( σ semester=’Spring’ ∧ year=2021 ( section ) ) \pi_\text{course\_id}(\sigma_{\text{semester='Fall'} \land \text{year=2020}}(\text{section})) - \pi_\text{course\_id}(\sigma_{\text{semester='Spring'} \land \text{year=2021}}(\text{section})) π course_id ( σ semester=’Fall’ ∧ year=2020 ( section )) − π course_id ( σ semester=’Spring’ ∧ year=2021 ( section ))
1 2 3 4 5 6 7 8 SELECT DISTINCT course_idFROM sectionWHERE semester = 'Fall' AND year = 2020 AND course_id NOT IN ( SELECT course_id FROM section WHERE semester = 'Spring' AND year = 2021 );
第四问 : (更新操作)
1 2 3 4 5 6 7 UPDATE instructorSET salary = salary * 1.05 WHERE salary > 70000 ;UPDATE instructorSET salary = salary * 1.10 WHERE salary <= 70000 ;
第五问 :
π salary ( instructor ) − π I 1. s a l a r y ( ρ I 1 ( instructor ) ⋈ I1.salary < I2.salary ρ I 2 ( instructor ) ) \pi_{\text{salary}}(\text{instructor}) - \pi_{I1.salary}( \rho_{I1}(\text{instructor}) \bowtie_{\text{I1.salary} < \text{I2.salary}} \rho_{I2}(\text{instructor}) ) π salary ( instructor ) − π I 1. s a l a ry ( ρ I 1 ( instructor ) ⋈ I1.salary < I2.salary ρ I 2 ( instructor ))
1 2 3 4 5 6 7 SELECT DISTINCT I1.salaryFROM instructor I1WHERE NOT EXISTS ( SELECT 1 FROM instructor I2 WHERE I2.salary > I1.salary );
参考和注解