一狂塘、函數(shù)和存儲(chǔ)過程
a)通過函數(shù)和存儲(chǔ)過程可以將業(yè)務(wù)邏輯保存在數(shù)據(jù)庫录煤,在需要的時(shí)候調(diào)用。比如學(xué)生在一個(gè)學(xué)期可以修的最大課程數(shù)荞胡、導(dǎo)師的最小授課數(shù)等妈踊,這些判斷具有比較復(fù)雜的邏輯,雖然在數(shù)據(jù)庫外也可以實(shí)現(xiàn)這樣的控制硝训,但用函數(shù)或存儲(chǔ)過程在數(shù)據(jù)庫的入口來把關(guān)响委,可以與應(yīng)用程序獨(dú)立開來,便于維護(hù)窖梁。但感覺將業(yè)務(wù)邏輯獨(dú)立寫在存儲(chǔ)過程也不一定就能便于維護(hù)赘风。
b)SQL標(biāo)準(zhǔn)規(guī)定的函數(shù)定義方法為:
create function dept count(dept_name varchar(20))
returns integer
begin
declare d_count integer;
select count(*) into d_count
from instructor
where instructor.dept_name= dept_name
return d count;
end
函數(shù)定義好后,可以在查詢語句中調(diào)用纵刘,就像內(nèi)置函數(shù)一樣:
select dept name, budget
from instructor
where dept count(dept name) > 12;
c)函數(shù)還可以返回表邀窃,稱為表函數(shù)(table functions),這相當(dāng)于帶參數(shù)的視圖
create function instructors of (dept_name varchar(20))
returns table ( ID varchar (5), name varchar (20), dept_name varchar (20), salary numeric (8,2))
return table
(select ID, name, dept_name, salary
from instructor
where instructor.dept_name = instructor of.dept_name);
類似的功能也可以使用存儲(chǔ)過程:
create procedure dept_count_proc(in dept_name varchar(20), out d_count integer) begin select count(*) into d_count
from instructor
where instructor.dept_name= dept_count proc.dept_name
end
in和out表示數(shù)據(jù)的輸入輸出假哎。存儲(chǔ)過程還可以重載瞬捕。
d)存儲(chǔ)過程和函數(shù)的區(qū)別:
函數(shù)只能通過return語句返回單個(gè)值或者表對(duì)象。而存儲(chǔ)過程不允許執(zhí)行return舵抹,但是通過out參數(shù)返回多個(gè)值肪虎;
函數(shù)是可以嵌入在sql中使用的,可以在select中調(diào)用,而存儲(chǔ)過程不行惧蛹;
函數(shù)限制比較多扇救,比如不能用臨時(shí)表,只能用表變量.還有一些函數(shù)都不可用等等.而存儲(chǔ)過程的限制相對(duì)就比較少香嗓;
一般來說迅腔,存儲(chǔ)過程實(shí)現(xiàn)的功能要復(fù)雜一點(diǎn),而函數(shù)的實(shí)現(xiàn)的功能針對(duì)性比較強(qiáng)靠娱。
二沧烈、SQL的語法結(jié)構(gòu)
a)SQL也像Java、C等語言一樣支持if像云、for等語法結(jié)構(gòu)锌雀,用declare聲明變量蚂夕、用set賦值,但一段SQL要寫在begin…end之間腋逆,使用begin atomic…end的話双抽,內(nèi)部的語句構(gòu)成一個(gè)事務(wù)。
b)while和repeat
while boolean expression do
sequence of statements;
end while
repeat
sequence of statements;
until boolean expression
end repeat
c)for
declare n integer default 0;
for r as
select budget from department where dept name = ‘Music‘
do
set n = n? r.budget
end for
d)if
if boolean expression
then statement or compound statement
elseif boolean expression
then statement or compound statement else statement or compound statement
end if
三闲礼、觸發(fā)器Trigger
a)觸發(fā)器包含兩個(gè)要素:被觸發(fā)的時(shí)機(jī)、被觸發(fā)后執(zhí)行的動(dòng)作铐维。
在數(shù)據(jù)庫自帶的一致性約束機(jī)制無法滿足業(yè)務(wù)需求時(shí)柬泽,可以用觸發(fā)器來限制;也可以實(shí)現(xiàn)監(jiān)控嫁蛇、報(bào)警锨并、自動(dòng)化等需求。
b)觸發(fā)器的創(chuàng)建
create trigger timeslot_check1 after insert on section
referencing new row as nrow
for each row
when (nrow.time slot_id not in (
select time slot_id
from time_slot))
begin
rollback
end;
為在section表insert時(shí)創(chuàng)建的觸發(fā)器睬棚,referencing new row as nrow會(huì)將被插入的行保存到nrow臨時(shí)變量第煮,然后使用for each row來遍歷。
除了插入操作抑党,刪除的觸發(fā)器寫法為:
create trigger timeslot_check2 after delete on timeslot
referencing old row as orow
for each row
when (orow.time slot_id not in (
select time slot_id
from time_slot)
and orow.time slot_id in (
select time slot_id from section)) begin
rollback
end;
臨時(shí)保存的是刪除前的舊行包警,那么update時(shí)新行、舊行都需要:
create trigger credits_earned after update of takes on (grade)
referencing new row as nrow
referencing old row as orow
for each row
when …
begin atomic
…
end;
只有takes.grade被更新時(shí)才會(huì)被觸發(fā)
c)除了用after定義動(dòng)作發(fā)生后的觸發(fā)器底靠,還可以使用before在動(dòng)作發(fā)生前觸發(fā)害晦;除了針對(duì)行的觸發(fā)器(for each row),還有針對(duì)表的觸發(fā)器暑中,對(duì)應(yīng)的語法有;refenencing old/new table as壹瘟、for each statement
d)觸發(fā)器雖然可以用來解決很多問題,但如果有替代方法鳄逾,便不推薦使用觸發(fā)器稻轨,因?yàn)橛|發(fā)器的錯(cuò)誤只能在運(yùn)行時(shí)發(fā)現(xiàn),而且多個(gè)觸發(fā)器的關(guān)聯(lián)會(huì)造成維護(hù)的困難雕凹。
學(xué)習(xí)資料:Database System Concepts, by Abraham Silberschatz, Henry F.Korth, S.Sudarshan