@3013216027
2016-01-28T05:18:57.000000Z
字数 18744
阅读 4078
数据库原理复习专栏
Movie(title, year, ...)string,date, integer等CHAR(n)和VARCHAR(n)BIT(n)和BIT VARYING(n)BOOLEAN,取值有{TRUE, FALSE, UNKNOWN}INT或INTEGERFLOAT或REAL单精度,DOUBLE双精度。FLOAT(n,d)表示小数后d位且有效数字共n位,DOUBLE(n,d类似DATE和TIMEadd, drop, createdefault ...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 COUNTselect title, length from ...select .... from ... where <condition>... where title LIKE 'Star'。下划线_表示一个字符,%表示若干个字符,''两个连续单引号表示单引号(相当于转义了)。使用ESCAPE 'x'将x作为一个转义字符来转义如%这样的特殊字符。NULL + 3、NULL - NULL结果均为NULLNULL < 3、NULL = NULL结果均为UNKNOWN... ORDER BY ... <ASC|DESC>。默认升序即ASCMovieStar.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 Rs > ALL Rs > ANY RNOT EXISTS……select name from (select ... ) pod where ...;CROSS JOINNATURAL JOINOUTER JOINR CROSS JOIN SR.name <> S.name或者R.name = S.name这样的简单形式。R INNER JOIN S ... ON R.属性1 = S.属性2或R JOIN。LEFT JOIN或LEFT OUTER JOINRIGHT JOIN或RIGHT OUTER JOINFULL 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、COUNTGROUP 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 uncommittedread committed、repeatable read、serializable>savepoint p1rollback to p1constraint fk_name foreign key (...) references table_name (...);CASCADESET NULL
create table education (from_date date not null,to_date date not null,id int not nullreferences student (id)on update cascadeon delete set null,primary key (id, from_date));
references ... deferrable initially deferred。事务结束后才检查约束。not nullcheckcheck ...constraint ...alter table ... drop constraint ...,alter table ... add constraint ...。create assertion <ast_name> check <condition>;
create assertion richPres check(not exists(select Studio.namfrom Studio, MovieExecwhere pres = cert and netWorth < 1000000));
create trigger <name><after|before> <update|delete|insert|update of <column name>>referenecingold row as oldtuplenew row as newtuplefor each row...
alter table Movies add constraint fkMoviesMovieExecforeign key (producer) references MovieExec (name);
alter table Movies add constraint fkMoviesMovieExecforeign key (producer) references MovieExec (name)on update set nullon delete set null;
alter table Movies add constraint fkMoviesMovieExecforeign key (producer) references MovieExec (name)on update cascadeon delete cascade;
alter table StarsIn add constraint fkStarsInMoviesforeign key (movieTitle) refereneces Movies (title);
alter table StarsIn add constraint fkStarsInMovieStarforeign 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 studioAddressUniqueunique 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 AvgNetWorthDeleteTriggerafter delete on MovieExecreferencingold tuple as OldTuplefor each rowbeginif (600000 > (select avg(netWorth) from MovieExec)) theninsert into MovieExec(name, address, cert, netWorth)values(OldTuple.name, OldTuple.address, OldTuple.cert, OldTuple.netWorth);end if;end
create trigger AvgNetWorthInsertTriggerafter insert on MovieExecreferencingnew tuple as NewTuplefor each rowbeginif (600000 > (select avg(netWorth) from MovieExec)) thendelete 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 triggercreate 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 insteadInsertDisneyComediesTriggerinstead of insert on DisneyComediesreferencingnew tuple as NewTuplefor each rowbegininsert into Movies(title, year, length, genre, studioName)values(NewTuple.title, NewTuple.year, NewTuple.year, 'comedy', 'Disney');end
create trigger insteadUpdateDisneyComediesTriggerinstead of update on DisneyComediesreferencingold tuple as OldTuplenew tuple as NewTuplefor each rowbeginupdate Movies set length = NewTuple.lengthwhere 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 ... endlabel1: ...条件分支
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 forselect length from Movies where studioName = s;declare newLength interger;declare movieCount integer;beginset mean = 0.0;set variance = 0.0;set movieCount = 0;open MovieCursor;movieLoop: LOOPfetch from MovieCursor into newLength;if eof then leave movieLoopend 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;beginset mean = 0.0;set variance = 0.0;set movieCount = 0;for movieLoop as MovieCursor cursor forselect length from movies where studioName = s;doset 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)beginselect sum(netWorth) into netWorthfrom MovieExecwhere cert = studioName;end
create function solveB (name char(32),address char(64)) returns intdeclare isMovieStar boolean default false;declare isMovieExec boolean default false;beginif (name, address) in (select name, address from MovieStar) thenset isMovieStar = true;end if;if (name, address) in (select name, address from MoveExec) thenset isMovieExec = true;end if;if isMovieStar and not isMovieExec thenreturn 1;elseif isMovieExec and not isMovieStar thenreturn 2;elseif isMovieExec and isMovieStar thenreturn 3;elsereturn 4;end if;end
create procedure solveC (in name char(32),out longest varchar(64),out longest2 varchar(64))begindeclare resCursor cursor forselect title from Movieswhere studioName = nameorder by length desc;declare eof condition for sqlstate '02000';open resCursor;if eof thenset longest = NULL;set longest2 = NULL;elsefetch from resCursor into longest;if eof thenset longest2 = NULL;elsefetch from resCursor into longest2;end if;end if;close resCursor;end
create function SolveD (sname char(32)) returns intdeclare res int default 0;beginselect min(year) into res fromMovies inner join StarsIn on title = movieTitleinner join MovieStar on starName = namewhere starName = sname and length > 120;if isnull(res) thenset res = 0;end if;return res;end
create procedure solveE (sname char(32))begindelete from MovieStar where name = sname;delete from Movieswhere title in (select movieTitle from StarsInwhere 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@localhostrename 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