3.12使用大学模式,用SQL写出如下查询。
a.创建一门课程"CS-001",其名称为"Weekly Seminar",学分为0.
insert into course values('CS-001', 'Weekly Seminar', NULL, 0);
插入失败,原因如下:
ERROR: new row for relation "course" violates check constraint "course_credits_check"
DETAIL: Failing row contains (CS-001, Weekly Seminar, null, 0).
SQL state: 23514
原来是违反了字段检查规则,因为我们在创建course关系的时候,对credits学分这个字段有限制,要求大于0。
create table course
(course_id varchar(8),
title varchar(50),
dept_name varchar(20),
credits numeric(2,0) check (credits > 0),
primary key (course_id),
foreign key (dept_name) references department
on delete set null
);
为了能成功插入数据,将学分改成1:
insert into course values('CS-001', 'Weekly Seminar', NULL, 1);
b.创建该课程在2009年秋季的一个课程段,sec_id为1.
insert into section values('CS-001', '1', 'Fall', 2009);
c.让Comp. Sci.系的每个学生都选修上述课程段。
insert into takes
select ID, 'CS-001', '1', 'Fall', 2009
from student where dept_name = 'Comp. Sci.';
d.删除名为Chavez的学生选修上述课程段的信息。
delete from takes where
course_id = 'CS-101' and sec_id = '1' and semester = 'Fall'
and year = 2009 and ID = (select ID from student where name = 'Chavez');
e.删除课程CS-001。如果在运行此删除语句之前,没有先删除这门课程的授课信息(课程段),会发现什么事情?
课程段关系对课程关系设置了外码依赖,当依赖的course关系删除某个课程的时候,自动删除该课程的所有授课信息,我们可以看一下课程段的DDL:
create table section
(course_id varchar(8),
sec_id varchar(8),
semester varchar(6)
check (semester in ('Fall', 'Winter', 'Spring', 'Summer')),
year numeric(4,0) check (year > 1701 and year < 2100),
building varchar(15),
room_number varchar(7),
time_slot_id varchar(4),
primary key (course_id, sec_id, semester, year),
foreign key (course_id) references course
on delete cascade,
foreign key (building, room_number) references classroom
on delete set null
);
注意这条语句
foreign key (course_id) references course
on delete cascade
现在我们开始删除课程CS-001,看看会发生什么。
delete from course where course_id = 'CS-001';
再检查一下课程段里是否还有该课程的授课信息:
select * from section where course_id = 'CS-001';
course_id | sec_id | semester | year | building | room_number | time_slot_id
-----------+--------+----------+------+----------+-------------+--------------
(0 rows)
f.删除课程名称中包含'database'的任意课程的任意课程段所对应的所有takes元组,在课程名的匹配中忽略大小写。
delete from takes where (course_id, sec_id, semester, year) in (
select course_id, sec_id, semester, year from section natural join
course where lower(title) like '%database%'
);
为了验证我们做的对不对,咱们先从course关系中找找包含database的课程都有哪些。
select * from course where lower(title) like '%database%';
course_id | title | dept_name | credits
-----------+--------------------------+------------+---------
CS-347 | Database System Concepts | Comp. Sci. | 3
(1 row)
这个课程的ID为CS-347,我们只要看看takes里有没有为这个ID的课程,就能知道刚才的删除有没有成功了。
select * from takes where course_id = 'CS-347';
id | course_id | sec_id | semester | year | grade
----+-----------+--------+----------+------+-------
(0 rows)