1. 程式人生 > >第3章 SQL 習題 - 3.12

第3章 SQL 習題 - 3.12

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)