@3013216027
2016-01-28T13:18:57.000000Z
字数 18744
阅读 3982
数据库原理复习专栏
Movie(title, year, ...)
string
,date
, integer
等CHAR(n)
和VARCHAR(n)
BIT(n)
和BIT VARYING(n)
BOOLEAN
,取值有{TRUE, FALSE, UNKNOWN}
INT
或INTEGER
FLOAT
或REAL
单精度,DOUBLE
双精度。FLOAT(n,d)
表示小数后d
位且有效数字共n
位,DOUBLE(n,d
类似DATE
和TIME
add
, drop
, create
default ...
primary key
、unique
符号形式 | 含义及说明 |
---|---|
交 | |
并 | |
差 | |
投影,从中选出属性 | |
选择,为条件 | |
笛卡尔积 | |
自然连接 | |
连接 | |
重命名 | |
消除重复 | |
扩展投影 | |
排序 | |
分组 | |
外连接 | |
聚集 |
create table Product (
maker varchar(64),
model varchar(32),
type varchar(16),
primary key (model)
);
create table PC (
model varchar(16),
speed float(6,2),
ram int,
hd int,
price float(8,2),
primary key (model)
);
create table Laptop (
model varchar(16),
speed float(6,2),
ram int,
hd int,
screen float(3,1),
price float(8,2),
primary key(model)
);
create table Printer (
model varchar(16),
color boolean default false,
type varchar(16),
price float(8,2),
primary key (model)
);
alter table Printer drop color;
alter table Laptop add od varchar(6) default 'none';
alter table Classes drop bore;
alter table Ships add yard varchar(32);
2.4.1
2.4.3
2.5.1
多值依赖
第四范式:在MVD上应用BCNF条件
元素 | 含义/作用 |
---|---|
矩形 | 实体集 |
菱形 | 联系 |
椭圆 | 属性 |
双框矩形 | 弱实体集 |
双框菱形 | 连接弱实体集的多对1联系 |
三角形 | 连接实体集和它的子类 |
连线段 | 连接<实体集-属性>或<实体集-联系> |
箭头 | 多对1关系(箭头指向"多对1"中的"1") |
下划线 | 被下划线标记的属性属于键的一部分 |
圆箭头 | 引用完整性(箭头指向被引用的实体集) |
边上的数字 | 度约束,如"<=10" |
SUM
AVG
MIN/MAX
COUNT
select title, length from ...
select .... from ... where <condition>
... where title LIKE 'Star'
。下划线_
表示一个字符,%
表示若干个字符,''
两个连续单引号表示单引号(相当于转义了)。使用ESCAPE 'x'
将x
作为一个转义字符来转义如%
这样的特殊字符。NULL + 3
、NULL - NULL
结果均为NULL
NULL < 3
、NULL = NULL
结果均为UNKNOWN
... ORDER BY ... <ASC|DESC>
。默认升序即ASC
MovieStar.address == MovieExec.address
。select A.name, B.name from Movie A, Movie B ...
UNION
、INTERSECT
、EXCEPT
。如(select name from MovieStar) EXCEPT (select name from MovieExec);
MySQL
不资瓷EXCEPT
,可以使用NOT IN
或者LEFT JOIN
来得到等价的语句。其中LEFT JOIN
有一些trick: (select s.no from s) except (select t.no from t where t.name = 'Bob');
select s.no from s left join t on s.no = t.no where ifnull(t.name, '') != 'Bob';
,其中的ifnull(exp1, exp2)
在exp1
非空时返回exp1
否则返回exp2
。EXISTS R
,当且仅当R
非空时为真s IN R
s > ALL R
s > ANY R
NOT EXISTS
……select name from (select ... ) pod where ...;
CROSS JOIN
NATURAL JOIN
OUTER JOIN
R CROSS JOIN S
R.name <> S.name
或者R.name = S.name
这样的简单形式。R INNER JOIN S ... ON R.属性1 = S.属性2
或R JOIN
。LEFT JOIN
或LEFT OUTER JOIN
RIGHT JOIN
或RIGHT OUTER JOIN
FULL JOIN
或FULL OUTER JOIN
。P.S. MySQL不资瓷全外连接R
和S
的所有同名字段为A1,A2,...,An
,除此之外R
还有B1,B2,...,Bm
,S
还有C1,C2,...,Ck
,那么自然连接select * from R NATURAL JOIN S
就等价于内连接select R.A1,R.A2,...,R.An, B1,B2,...,Bm,C1,C2,...,Ck from R inner join S on R.A1=S.A1 and R.A2=S.A2 and ... and R.An=S.An
。自然连接不能像内连接那样使用ON R.id = S.emp_no
来指定连接条件,它仅对同名字段做相等条件判断。select distinct ...
<UNION|INTERSECT|EXCEPT> ALL
来避免消除重复。SUM
、AVG
、MIN
、COUNT
GROUP BY ... HAVING...
GROUP BY
的属性不被HAVING
中的聚集操作作用。insert into ... (...) values (...);
DELETE FROM ... (where ...);
UPDATE ... set ... where ...;
隔离级别(isolation) | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
未提交读 | 是 | 是 | 是 |
已提交读 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
可串行化 | 否 | 否 | 否 |
set transaction read only;
set transaction read write;
set transaction isolation read uncommitted
read committed
、repeatable read
、serializable>
savepoint p1
rollback to p1
constraint fk_name foreign key (...) references table_name (...);
CASCADE
SET NULL
create table education (
from_date date not null,
to_date date not null,
id int not null
references student (id)
on update cascade
on delete set null,
primary key (id, from_date)
);
references ... deferrable initially deferred
。事务结束后才检查约束。not null
check
check ...
constraint ...
alter table ... drop constraint ...
,alter table ... add constraint ...
。create assertion <ast_name> check <condition>;
create assertion richPres check
(not exists
(select Studio.nam
from Studio, MovieExec
where pres = cert and netWorth < 1000000
)
);
create trigger <name>
<after|before> <update|delete|insert|update of <column name>>
referenecing
old row as oldtuple
new row as newtuple
for each row
...
alter table Movies add constraint fkMoviesMovieExec
foreign key (producer) references MovieExec (name);
alter table Movies add constraint fkMoviesMovieExec
foreign key (producer) references MovieExec (name)
on update set null
on delete set null;
alter table Movies add constraint fkMoviesMovieExec
foreign key (producer) references MovieExec (name)
on update cascade
on delete cascade;
alter table StarsIn add constraint fkStarsInMovies
foreign key (movieTitle) refereneces Movies (title);
alter table StarsIn add constraint fkStarsInMovieStar
foreign key (movieStar) references MovieStar(name)
on delete cascade;
alter table StarsIn add check (
movieYear < (select year(now()) - year(birthdate) from MovieStar where name = starName)
);
或者
alter table StarsIn add check (
starName in (select name from MovieStar where year(birthdate) > movieYear)
);
alter table Studio add constraint studioAddressUnique
unique key (address);
alter table MovieExec add check (
name not in (select name from MovieStar)
);
alter table Studio add check (
name in (select studioName from Movies)
);
alter table Movies add check (
producer not in (select name from MovieExec)
or
(select cert from MovieExec where name = producer)
= studioName
);
create trigger AvgNetWorthDeleteTrigger
after delete on MovieExec
referencing
old tuple as OldTuple
for each row
begin
if (600000 > (select avg(netWorth) from MovieExec)) then
insert into MovieExec
(name, address, cert, netWorth)
values
(OldTuple.name, OldTuple.address, OldTuple.cert, OldTuple.netWorth);
end if;
end
create trigger AvgNetWorthInsertTrigger
after insert on MovieExec
referencing
new tuple as NewTuple
for each row
begin
if (600000 > (select avg(netWorth) from MovieExec)) then
delete from MovieExec where name = NewTuple.name;
--此处应该用主键来定位
end if;
end
create view <name> as <...>;
select ... from <view_name> ...
create view <name>(column names...) as ...
,其它方案:create view <name> as select <column> as <new_name> ...
drop view <view name>;
WHERE
子句在子查询中不能使用该关系FROM
语句只能包含一个关系,不能再有其他关系SELECT
语句必须选出所有没有默认值的属性,使得插入时没有选出的属性可以被赋予默认值或者空值(NULL)instead of trigger
create index <index name> on <table name>(column name(s));
create materialized view <view name> as ...
Movies(title, year, length, genre, studioName, producer)
,若原关系中studioName
、genre
和producer
均有默认值或者可以为空则该视图满足可更新视图的定义,因此是可更新视图。
create trigger insteadInsertDisneyComediesTrigger
instead of insert on DisneyComedies
referencing
new tuple as NewTuple
for each row
begin
insert into Movies
(title, year, length, genre, studioName)
values
(NewTuple.title, NewTuple.year, NewTuple.year, 'comedy', 'Disney');
end
create trigger insteadUpdateDisneyComediesTrigger
instead of update on DisneyComedies
referencing
old tuple as OldTuple
new tuple as NewTuple
for each row
begin
update Movies set length = NewTuple.length
where title = OldTuple.title and year = Oldtuple.year;
end
create procedure <name> (参数) <局部声明> <过程体>
;create function <name> (<参数>) returns <返回类型> <局部声明> <函数体>
call <过程名> (<参数>);
,在宿主语言中则是EXEC SQL CALL Foo(:x, 3);
select test(3);
declare <name> <type> (default <value>);
set <val> = <expression>;
begin ... end
label1: ...
条件分支
if ... then ... (elseif ... then ...) end if;
循环
LOOP <body> END LOOP;
,退出循环LEAVE <循环标识>;
,使用"EOF": DECLARE eof CONDITION FOR SQLSTATE '02000';
,声明游标: DECLARE myCursor CURSOR FOR <select length from ... where ...>;
然后fetch from myCursor into ...
delimiter //
create procedure test (
in s char(15),
out mean real,
out variance real
)
declare eof condition for sqlstate '02000';
declare MovieCursor cursor for
select length from Movies where studioName = s;
declare newLength interger;
declare movieCount integer;
begin
set mean = 0.0;
set variance = 0.0;
set movieCount = 0;
open MovieCursor;
movieLoop: LOOP
fetch from MovieCursor into newLength;
if eof then leave movieLoop
end if;
set movieCount = movieCount + 1;
set mean = mean + newLength;
set variance = variance + newLength * newLength;
end loop;
set mean = mean / movieCount;
set variance = variance / movieCount - mean * mean;
close MovieCursor;
end//
delimiter ;
delimiter //
create procedure test (
in s char(15),
out mean real,
out variance real
)
declare movieCount integer;
begin
set mean = 0.0;
set variance = 0.0;
set movieCount = 0;
for movieLoop as MovieCursor cursor for
select length from movies where studioName = s;
do
set movieCount = movieCount + 1;
set mean = mean + length;
set variance = variance + length * length;
end for;
set mean = mean / movieCount;
set variance = variance / movieCount - mean * mean;
end//
delimiter ;
create procedure solveA (
in studioName char(32),
out netWorth real
)
begin
select sum(netWorth) into netWorth
from MovieExec
where cert = studioName;
end
create function solveB (
name char(32),
address char(64)
) returns int
declare isMovieStar boolean default false;
declare isMovieExec boolean default false;
begin
if (name, address) in (select name, address from MovieStar) then
set isMovieStar = true;
end if;
if (name, address) in (select name, address from MoveExec) then
set isMovieExec = true;
end if;
if isMovieStar and not isMovieExec then
return 1;
elseif isMovieExec and not isMovieStar then
return 2;
elseif isMovieExec and isMovieStar then
return 3;
else
return 4;
end if;
end
create procedure solveC (
in name char(32),
out longest varchar(64),
out longest2 varchar(64)
)
begin
declare resCursor cursor for
select title from Movies
where studioName = name
order by length desc;
declare eof condition for sqlstate '02000';
open resCursor;
if eof then
set longest = NULL;
set longest2 = NULL;
else
fetch from resCursor into longest;
if eof then
set longest2 = NULL;
else
fetch from resCursor into longest2;
end if;
end if;
close resCursor;
end
create function SolveD (
sname char(32)
) returns int
declare res int default 0;
begin
select min(year) into res from
Movies inner join StarsIn on title = movieTitle
inner join MovieStar on starName = name
where starName = sname and length > 120;
if isnull(res) then
set res = 0;
end if;
return res;
end
create procedure solveE (
sname char(32)
)
begin
delete from MovieStar where name = sname;
delete from Movies
where title in (
select movieTitle from StarsIn
where starName = sname
);
delete from StarsIn where starName = sname;
end
create user dong identified by 'qyetfu';
grant all privileges on *.* to dong@localhost;
revoke delete on *.* from dong@localhost;
drop user dong@localhost
rename user dong@localhost to dong;
INPUT(X)
:把包含元素X
的磁盘块拷贝到主存缓冲区READ(X, t)
:把元素X
拷贝到变量t
中,如果X
不在主存缓冲区,则先INPUT(X)
WRITE(X, t)
:把局部变量t
的值拷贝到主存缓冲区中的数据库元素X
中,如果X
不在主存缓冲区,则先INPUT(X)
OUTPUT(X)
:将包含X
的缓冲区中的块拷贝回磁盘<START T>
:事务T已开始。<COMMIT T>
:事务T已成功完成并且对数据库元素不再会有修改。<ABORT T>
:事务T不能成功完成。<T, X, v>
:更新日志,表示事务T改变了元素X,且X原来的值为v。FLUSH LOG
刷新日志,将日志从主存缓冲区写入磁盘<T, X, v>
,则:若事务T的COMMIT记录已经被扫描到,则什么也不做。否则,T是一个未完成的事务,将数据库元素X的值改为v,然后刷新日志。<CKPT>
,并再次刷新日志<START CKPT(T1, ..., TK)>
并刷新日志,其中是当前所有的活跃事务的标识符<END CKPT>
并刷新日志和undo的区别
redo日志规则
<T, X, v>
表示事务T为元素X写入新值vredo日志恢复
<T, X, v>
: <ABORT T>
并刷新日志<T, X, v, w>
:事务T改变元素X的值,从v变为w
<START U>
<U, A, 10>
<START T>
<T, B, 20>
<U, C, 30>
<T, D, 40>
<COMMIT T>
<U, E, 50>
<COMMIT U>
<U, A, 10>
,U是一个没COMMIT的事务,因此把A的值恢复为10<T, D, 40>
,但T已经COMMIT,跳过<U, C, 30>
,U未COMMIT,把C的值恢复为30<T, B, 20>
,但T已经COMMIT,跳过<U, A, 10>
,U未COMMIT,把A恢复为10<U, E, 50>
,U未COMMIT,把E的值恢复为50<T, D, 40>
,但T已经COMMIT,跳过<U, C, 30>
,U未COMMIT,把C的值恢复为30<T, B, 20>
,但T已经COMMIT,跳过<U, A, 10>
,U未COMMIT,把A恢复为10<U, E, 50>
,但U已经COMMIT,跳过<T, D, 40>
,但T已经COMMIT,跳过<U, C, 30>
,但U已经COMMIT,跳过<T, B, 20>
,但T已经COMMIT,跳过<U, A, 10>
,但U已经COMMIT,跳过冲突可串行化
冲突可串行化判断:事务优先于记作,条件是存在中的事务和中的事务满足:
对应优先图上,有一个T_1指向T_2的有向边。最后如果优先图中包含环,则其调度就不是冲突可串行化的。
相容矩阵
申请的锁 | |||
---|---|---|---|
共享锁S | 排他锁X | ||
持有锁的模式 | 共享锁S | 是 | 否 |
排他锁X | 否 | 否 |
更新锁
\ | 共享锁S | 排他锁X | 更新锁U |
---|---|---|---|
共享锁S | 是 | 否 | 是 |
排他锁X | 否 | 否 | 否 |
更新锁U | 否 | 否 | 否 |
a
b
c
d
e
f
g
h
i
j
k