常用SQL第二部分
首先我們建立兩個表以供後面使用,分別是學生資訊表student和學生選課資訊表takes,如下:
create table student(
id varchar(10),
name varchar(15),
department varchar(20),
primary key(id));
create table takes(
id varchar(10),
course_id varchar(5),
course_name varchar(10),
primary key(id,course_id)
);
連線表示式
natureal join表示從兩個表中選擇這樣的元組:他們在具有相同屬性名上的取值相同。例如我們查詢計算機系的學生所選的課程:
select s.id course_name from student as s natural join takes where s.department = ‘計算機’
SQL也可以指定任意的連線條件,on條件允許在參與連線的關係上設定通用的謂詞,例如查詢所有學生所選的課:
select * from student join takes on student.id = takes.id
自然查詢雖然功能很強,但是也有不可避免的缺點,他所查出的必須是兩個關係中都有的且同名屬性相同的元組,但是那些只有一個關係中有的元組就被丟棄了。這樣就會造成一些問題,例如我們想查詢所有學生的選課資訊,但是如果某些學生沒有選課,用自然連線的方式就會把這些學生丟棄,這是我們所不希望看到的,為此我們引入了外連線。
1、左外連線(left outer join):只保留出現在左外連線運算之前(左邊)的關係中的元組
2、右外連線(right outer join):只保留出現在右外連線之後(右邊)的關係中的元組
3、全外連線(full outer join):保留出現在兩個關係中的元組
例如:
select * from student natural left outer join takes
檢視
有時候出於安全考慮我們可能不想讓某些人看到或者操作資料庫中的全部資料,比如說學生可以知道老師的姓名、學院等資訊,但是沒有權利看到老師的工資資訊。為了滿足這種需求SQL允許通過查詢來定義“虛關係”,虛關係並不預先計算或者儲存,而是使用的時候才進行計算。任何像這種不是邏輯模型的一部分,但作為虛關係對使用者可見的關係稱為檢視。我們用create view來定義檢視,格式如下:
create view v as (查詢表示式)
例如:create view basic as select name,department from student
一些特定的資料庫允許儲存檢視關係,且保證如果用於定義檢視的實際關係改變,檢視也跟著修改。這樣的檢視被稱為物化檢視。注意:我們一般不允許對檢視關係進行修改,雖然有些也可以,但是強烈不建議。
單關係上的約束
在建立表時除了主碼約束以外,還有其它約束,例如:not null,unique,check(謂詞),外碼。為了方便說明,我們建立一個表,如下:
create table student(
id varchar(10) not null,
name varchar(20),
sex varchar(2),
department varchar(20),
unique(id),
primary key(id),
foreign key(department)references department,
check(sex in(‘男’,‘女’))
);
涉及到外碼就會牽扯到一個概念,叫做參照完整性或者子集依賴:關係r1,r2的屬性集分別是R1和R2,主碼分別是K1和K2,如果要求對r2中任意元組t2,均存在r1中元組t1,使得t1.K1 = t2.b,我們稱R2子集中的b為參照關係r1中K1的外碼。預設情況下SQL中外碼參照的是其他關係的主碼。這樣就存在了一個問題:當被參照關係發生刪除或者更新時就違反了參照完整性,為了解決這個問題我們可以在foreign key子句中指明:如果被參照關係上的刪除或者更新動作違反了約束,那麼系統就必須採取一些步驟通過修改參照關係中的元組來恢復完整性約束,如下:
create table student(
foreign key(department)reference department
on delete cascade
on update cascade,
)
斷言
一個斷言就是一個謂詞,用來檢測資料庫是否滿足某些條件,域約束和參照完整性約束是斷言的一種特殊形式。斷言格式如下:
create assertion name check predicate
比如,我們想要對student關係中的每一個學生他的total_cred總分等於他所修課程的學分總和:
create assertion credit check
(not exits (
select id from student where total_cred<>
(select sum(credits) from takes where student.id = takes.id)
)
其中student中記錄的是學生基本資訊,takes記錄的是學生選課資訊和分數。由於SQL不提供for all x,P(x)的結構(p是謂詞),我們要用not exits x such that not P(x)來實現。
SQL的資料型別
日期和時間
data:日曆日期,年月日,例如:2018-04-04
time:時鐘時間,時分秒,例如:09:28:34
timestamp:date和time的組合2018-04-05 10:35:21
其中time和timestamp的秒部分可以是小數。
我們可以用cast str as t的形式把一個字串轉化為型別t,t是date、time或者timestamp的一種。例如:cast ‘2018-04-06’ as data
我們也可以用extract (field from d)從data或time中提取單獨的區域,區域可以使year、month、day、hour、minute、second。例如:extract (year from ‘2018-04-06’)
我們可以用current_data返回當前日期,或者用current_time或者localtime來返回當前時間,或者用current_timestamp或localtimestamp返回本地日期和時間。
我們還可以對日期和時間進行加減計算,例如,x,y都是data型別的,那麼x-y就是天數間隔
預設值
SQL允許指定屬性的預設值,例如:
create table student(
……
credit numeric(3,0)default 0,
…..
)
大物件型別
SQL允許你在資料庫中儲存一些圖片、視訊等非常大的資料,它將這些大物件分為兩類:字元資料(clob)和二進位制資料(blob),例如,我們可以宣告屬性:
book clob(10K)
image blob(10MB)
movie blob(3GB)
其實資料庫並沒有把這些大物件真正的存入其中,而只是存了一個這些大物件的索引而已。
自定義型別
SQL允許使用者自定義資料型別,分為兩類:獨特型別和結構化資料型別。
我們可以使用create type來建立新型別,如下:
create type dollor as numerical(10,2)final
create type pound as numerical(10,2)final
意思就是我們建立了一個名為“dollor”和“pound”的資料型別,共有10位,其中有兩位小數。雖然這兩個資料型別的本質是一樣的,但是當我們嘗試將一個pound型別的資料賦予給一個dollor型別的資料時會導致一個編譯時錯誤,這是因為我們所建立的是強型別。為了解決這個問題人們引入了“域”這個概念,示例如下:
create domain dollor as numerica(10,2)not null
域和型別之間的區別:
1、域可以宣告約束
2、域不是強型別的,所以一個域型別的值可以賦給另一個域型別。
授權
SQL的標準有select、insert、delete和update許可權。我們可以用grant關鍵字來進行授權,如下:
grant <許可權名稱> on <關係或者檢視> to <使用者或角色>
同樣我們也可以用revoke關鍵字來收回許可權,如下:
revoke<許可權名稱> on <關係或者檢視> from <使用者或角色>
角色
考慮一個問題:我們要將某些許可權賦給某一類人,如果一個一個的寫grant語句進行授權就會十分麻煩。一個更好的解決方案是:指明這類人的許可權,然後標出這類所在的資料庫。系統用著兩條資訊給這類人自動授權。於是就引入了角色這個概念。在資料庫中建立一個角色集合,可以給角色授予許可權。每個資料庫使用者被賦予一組他有權扮演的角色。例如:
create role teacher
然後給角色賦予許可權
grant select on student to teacher
角色可以授權給使用者或者其他角色
grant teacher to 某某
create role dean
grant teacher to dean
檢視授權
如果我們只想讓某人僅有權查詢一個關係中的部分資料該怎麼辦呢?這時候檢視就又顯示處它的作用了。你可以先建立一個檢視,然後讓使用者去查詢這個檢視。當然前提是你要賦予這個使用者查詢的權利。
許可權的轉移
如果我們希望給一個使用者授予某些權利,並且執行他把這些權力再賦給別人,我們可以用with grant option來實現,例如:
grant select on teacher to 某某 with grant option
許可權收回
如果我們將許可權賦給了a,a又將許可權賦給了b,現在我們將a的許可權收回,那麼b的許可權也會被一起收回,這就是級聯收回。級聯是預設的行為。當然我們也可以用restrict來防止級聯收回,如下:
revoke select on teacher from a restrict
下面的revoke僅僅收回grant option,並不收回select權利:
revoke grant option for select on teacher from a