@SovietPower
2022-06-13T20:39:27.000000Z
字数 11181
阅读 1213
DB
数据库常用关系代数符号:https://billc.io/2020/04/latex-relational-algebra/
.
2.14
a.
b.
c.
d.
2.15
a.
b.
c.
2.18
a.
b.
c.
d.
e.
3.11
a.
select distinct ID, name
from student natural join takes natural course
where course.dept_name='Comp. Sci.'
b.
select ID, name
from student
except
select distinct ID, name
from student natural join takes
where year<2017
c.
select dept_name, max(salary)
from instructor
group by dept_name
d.
select min(max_salary)
from (
select dept_name, max(salary)
from instructor
group by dept_name ) as dept_salary(dept, max_salary)
3.12
a.
insert into course
values('CS-001', 'Weekly Seminar', 'Comp. Sci.', 0)
b.
insert into section(course_id, sec_id, semester, year)
values('CS-001', 1, 'Autumn', 2017)
c.
insert into takes(ID, course_id, sec_id, semester, year)
select ID, 'CS-001', 1, 'Autumn', 2017
from student
where dept_name='Comp. Sci.'
d.
delete from takes
where ID=12345 and course_id='CS-001'
and sec_id=1 and semester='Autumn' and year=2017
e.
delete from takes
where course_id='CS-001'
delete from section
where course_id='CS-001'
delete from course
where course_id='CS-001'
因为section
有引用course
的外键约束,先删除course
会导致违反完整性约束,删除失败。
f.
delete from takes
where course_id in
select course_id
from course
where lower(title) like '%advanced%'
3.15
a.
select ID, customer_name
from customer
except
select C.ID, C.customer_name
from customer as C
where not exists(
select branch_name
from branch
where branch_city='Brooklyn'
except
select branch_name
from customer natural join depositor natural join account
where customer.ID=C.ID )
b.
select sum(amount)
from loan
c.
select branch_name
from branch
where assets > some(
select assets
from branch
where branch_city='Brooklyn' )
3.16
a.
select ID, person_name
from employee natural join works natural join company
b.
select E.ID, E.person_name
from employee natural join manager_id as E, employee as M
where E.manager_id=M.id
and E.street=M.street and E.city=M.city
c.
select ID, person_name
from employee natural join works as E
where E.salary > (
select avg(salary)
from works
where company_name=E.company_name )
d.
select company_name, sum(salary)
from works
group by company_name
having sum(salary)<= all (
select sum(salary)
from works
group by company_name )
4.15
select *
from section join classroom using (building, room_number)
4.16
select ID
from student natural left outer join takes
where course_id is null
4.17
select ID
from student left outer join advisor on ID=s_ID
where i_ID is null
5.12
import java.util.Scanner;
import static java.lang.System.out;
// JDBC
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.DriverManager;
// mysql
import com.mysql.cj.exceptions.MysqlErrorNumbers;
// class
public class Exercise_5_12
{
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/db_exercise?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
static Connection conn;
public static void main(String... args)
{
// Connect to DB
// a.
Scanner scanner = new Scanner(System.in);
int ret;
if ((ret=ConnectDB(scanner))!=0)
{
while(ret == MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR)
{
out.println("Invalid Password. Access denied.");
ret = ConnectDB(scanner);
}
if (ret != 0) {
Fail();
return;
}
}
// b.
if (!TaskB(scanner)) {
Fail();
return;
}
// c.
int id = TaskC(scanner);
if (id == 0) {
Fail();
return;
}
// d.
TaskD(id);
// Finish and close conn and stmt
CloseConnection(conn);
out.println("\nfinish!");
}
static void Fail()
{
out.println("Operation failed. Please check your config.");
}
static boolean TaskB(Scanner scanner)
{
boolean done = false;
ResultSet rs = null;
PreparedStatement pStmt = null;
out.print("\nB: type the name: ");
while(true)
{
String query = scanner.next();
try
{
pStmt = conn.prepareStatement(
"SELECT id, name FROM instructor "+
"WHERE lower(name) like ?"
);
pStmt.setString(1, "%"+query+"%");
rs = pStmt.executeQuery();
while(rs.next())
{
done = true;
out.printf("%d %s\n", rs.getInt(1), rs.getString(2));
}
} catch (SQLException se) {
se.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
// out.println(pStmt.toString());
if (done) break;
out.println("No such ID found.");
}
CloseResultSet(rs);
ClosePreparedStatement(pStmt);
return true;
}
static int TaskC(Scanner scanner)
{
int ret = 0;
ResultSet rs = null;
PreparedStatement pStmt = null;
out.print("\nC: type the ID: ");
int query = scanner.nextInt();
if (query<0 || query>99999)
{
out.println("Invalid id.");
return 0;
}
try
{
pStmt = conn.prepareStatement(
"SELECT id, name FROM instructor "+
"WHERE id=?"
);
pStmt.setInt(1, query);
rs = pStmt.executeQuery();
if (rs.next())
{
ret = rs.getInt(1);
out.printf("ID Found:\n%d %s\n", rs.getInt(1), rs.getString(2));
}
else
out.println("No such name found. Program exiting.");
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
CloseResultSet(rs);
ClosePreparedStatement(pStmt);
return ret;
}
static void TaskD(int id)
{
boolean ret = false;
ResultSet rs = null;
PreparedStatement pStmt = null;
out.printf("\nD: checking ID: %d\n", id);
try
{
pStmt = conn.prepareStatement(
"WITH temp(course_id, sec_id, semester, year, cnt) AS "+
"(SELECT course_id, sec_id, semester, year, count(*) "+
"FROM teaches inner join takes using(course_id, sec_id, semester, year) "+
"WHERE teaches.id=? "+
"GROUP BY course_id, sec_id, semester, year) "+
"SELECT dept_name, course_id, title, sec_id, semester, year, cnt "+
"FROM course join temp using(course_id) "+
"ORDER BY dept_name, course_id, year, semester"
);
pStmt.setInt(1, id);
rs = pStmt.executeQuery();
while (rs.next())
{
ret = true;
out.printf("%s %s %s %d %s %d %d\n", rs.getString(1), rs.getString(2), rs.getString(3), rs.getInt(4), rs.getString(5), rs.getInt(6), rs.getInt(7));
}
} catch (SQLException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
CloseResultSet(rs);
ClosePreparedStatement(pStmt);
if (!ret)
out.println("He/She hasn't taught any course yet.");
}
static int ConnectDB(Scanner scanner)
{
out.println("Input your username and password:");
// String username = "root";
// String password = "GXB";
String username = scanner.next();
String password = scanner.next();
try
{
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, username, password);
}
catch(SQLException se)
{
if (se.getErrorCode() != MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR)
se.printStackTrace();
return se.getErrorCode();
}
catch(Exception e)
{
e.printStackTrace();
return -1;
}
return 0;
}
static void CloseConnection(Connection conn)
{
try {
if(conn!=null) conn.close();
} catch(SQLException se) {
se.printStackTrace();
}
}
static void CloseStatement(Statement stmt)
{
try {
if(stmt!=null) stmt.close();
} catch(SQLException se) {
se.printStackTrace();
}
}
static void ClosePreparedStatement(PreparedStatement pStmt)
{
try {
if(pStmt!=null) pStmt.close();
} catch(SQLException se) {
se.printStackTrace();
}
}
static void CloseResultSet(ResultSet rs)
{
try {
if(rs!=null) rs.close();
} catch(SQLException se) {
se.printStackTrace();
}
}
}
5.18
修改call
处的参数以查看结果。
使用//
作为delimiter。
drop procedure if exists find_name;
create procedure find_name(in keyword varchar(64))
begin
select id, name
from instructor
where lower(name) like concat('%', keyword, '%');
end
//
call find_name('ri');//
drop procedure if exists print_error;
create procedure print_error(in Message varchar(100))
begin
select 'Error', Message;
end
//
drop procedure if exists query_teacher_by_id;
create procedure query_teacher_by_id(in query int)
begin
declare res int;
if (query<0 or query>99999) then
call print_error("Invalid ID");
else
select id into res
from instructor
where id=query;
if (res is null) then
call print_error("No such id");
else
WITH temp(course_id, sec_id, semester, year, cnt) AS
(SELECT course_id, sec_id, semester, year, count(*)
FROM teaches inner join takes using(course_id, sec_id, semester, year)
WHERE teaches.id=query
GROUP BY course_id, sec_id, semester, year)
SELECT dept_name, course_id, title, sec_id, semester, year, cnt
FROM course join temp using(course_id)
ORDER BY dept_name, course_id, year, semester;
end if;
end if;
end
//
call query_teacher_by_id(10001);//
6.3
每场比赛参加的队员及其得分,用关系play
表示。
派生属性:
参加比赛数played_match()
: 统计该player_id
在play
中出现多少次。
比赛总得分total_score()
:统计该player_id
在play
中的得分之和。
6.20 b
6.23
7.31
只能推出,不能推出,所以不是超键。
因为,R变为。
是BCNF。没有依赖和有关,所以也是BCNF。所以分解完成。
与有关的依赖都需连接,所以不是保持依赖的。
判断BCNF好像错了,需要用F的闭包而不是F。所以应该用检测算法(检查所有属性子集)。
分解算法好像也不对?
7.32
a. 。
,该依赖去掉或都不再成立,去掉则无法推出,去掉依然可以推出,所以可以去掉。
b.
不成立,所以不是超键,由分为。是BCNF。没有一个依赖的两边都属于,所以也是BCNF。
c. 无损。
成立,所以无损。
d. 不保持。
后两个依赖在单独模式都不能验证,所以不是保持依赖的。
7.33
a. 。
右侧都没有,所以一定包含于候选键。又因为是候选键,所以只有一个。
b. 。
1. ,的是无关属性,换为。换为。
2. 合并两个得到。
c.
1. 令。
2. 添加。
3. 删除。
d.
7.34
a. 。(少了ACEGH)
右侧都没有,所以一定包含于候选键。
再加一个可推出,再加一个可推出,所以有两个。
b. 。
1. ,的是无关属性,换为。同理换为,换为。
2. 不能再更改。
c.
1. 令。
2. 添加。
3. 删除。
d.
叶节点之间都有连接,但叶子太多改起来很麻烦就不加了
1.
(1, 2, 5, 6, 8, 10, 18, 27, 32, 39, 41, 45, 52, 58, 73, 80, 91, 99)
delete 8.
delete 10.
insert 46.
delete 52
delete 32.
delete 39.
delete 41.
delete 45.
2.
(apple, pear, apricot, peach, grape, banana, pineapple, plum, watermelon, orange, lemon, mango, strawberry, medlar, mulberry, nectarine, cherry, pomegranate)
15.17
a.
块。
块。
第一阶段需次块传输,初始归并段数量个。
归并次数为。
块传输数,寻道次数。
块传输时间,寻道时间。
代价。
时:
。
时:
。
b.
时:
遍
时:
遍
c.
块传输时间,延迟时间。
时:
。
时:
。
15.19
1. 将两棵B+树的叶子节点进行归并,结果文件包含两个关系的元组地址,其中值相同的元组地址会放在一起,在排序时会被一起移动。
2. 将结果文件按一个关系的元组地址进行排序(移动时一起移动值相同的另一个关系的元组地址),然后按顺序读取、将这些元组地址替换为实际的元组。此时结果文件包含已排序的元组和未排序的元组地址。
3. 然后同原算法,对另一个关系的元组地址再进行排序、按序读取。
15.20
设:,。
包含的块数分别为:,。
1. 设B+树每个叶节点最多包含索引 个。
总传输块数:
总寻道次数:
结果文件包含的块数。
2.
设为缓冲区最大用于排序的块数。
初始归并段数量个。
归并次数。
按序读取、替换元组需要:按序读取原关系的元组、按序读取并写回每个排好序的块。因为交替取这两个块,所以每块都要寻道?
总传输块数:
总寻道次数:
3.
用到的和第二步的元组数量相同,所以排序代价相同。只不过最后替换时不用写回。
总传输块数:
总寻道次数:
17.15
$$
17.20
$$
18.12
$$
18.25
$$
18.27
$$
19.21
$$
19.23
$$
19.25
$$