摘 要: 兼容Oracle PL/SQL V2.3 語言規(guī)范,,基于國產(chǎn)數(shù)據(jù)庫管理系統(tǒng)" title="管理系統(tǒng)">管理系統(tǒng)GKD-Base" title="GKD-Base">GKD-Base內(nèi)核與PL/SQL引擎,,提出了Instead-Of視圖觸發(fā)器的編譯存儲和點(diǎn)火執(zhí)行算法,并設(shè)計(jì)實(shí)現(xiàn)了Instead-Of 視圖觸發(fā)器編譯及執(zhí)行處理模塊" title="處理模塊">處理模塊,。從而在GKD-Base上實(shí)現(xiàn)了Instead-Of視圖觸發(fā)器機(jī)制,,擴(kuò)展了國產(chǎn)數(shù)據(jù)庫GKD-Base功能,。
關(guān)鍵詞: PL/SQL引擎 Instead-Of觸發(fā)器
GKD-Base是一個(gè)具有自主知識產(chǎn)權(quán)的數(shù)據(jù)庫管理系統(tǒng),,經(jīng)過十幾年的發(fā)展和應(yīng)用,,該系統(tǒng)已經(jīng)被證明是穩(wěn)定可靠的。但是,,隨著應(yīng)用需求向深度和廣度的發(fā)展,,GKD-Base在很多方面都暴露出了不足,,如不支持過程式SQL語言,、不支持存儲過程和函數(shù)、缺少觸發(fā)器功能等,,這都為GKD-Base數(shù)據(jù)庫管理系統(tǒng)的進(jìn)一步推廣應(yīng)用帶來了不小的障礙,。
為此筆者開發(fā)了GKD-Base PL/SQL引擎,其兼容Oracle PL/SQLV2.3規(guī)范,。進(jìn)而在引擎的基礎(chǔ)上實(shí)現(xiàn)了GKD-Base DML觸發(fā)器功能[1],。但目前GKD-Base對于視圖更新的支持還很不夠,對于連接視圖的更新有著十分嚴(yán)格的限制,。國外數(shù)據(jù)庫系統(tǒng)" title="數(shù)據(jù)庫系統(tǒng)">數(shù)據(jù)庫系統(tǒng)如Oracle[2],、SQL Server[3]、PostgreSQL[4]等都提供了所謂的Instead-Of視圖觸發(fā)器來支持視圖更新。定義有Instead-Of觸發(fā)器的視圖被DML語句操作時(shí),,相應(yīng)的DML語句不執(zhí)行,,而觸發(fā)器體被執(zhí)行,于是用戶可以按照自己定義的語義修改定義視圖的基本表,,以達(dá)到修改視圖的目的,。因此,為了使GKD-Base適應(yīng)應(yīng)用需求的發(fā)展,,在GKD-Base PL/SQL引擎的基礎(chǔ)上實(shí)現(xiàn)了GKD-Base Instead-Of視圖觸發(fā)器功能[1],。
1 視圖更新歧義問題
視圖是虛擬的關(guān)系,數(shù)據(jù)庫系統(tǒng)中只存儲它的定義,,不存儲元組數(shù)據(jù),。一個(gè)視圖可以看成一個(gè)臨時(shí)關(guān)系,視圖是產(chǎn)生這種臨時(shí)關(guān)系的查詢定義[5],。
由于視圖是虛擬的關(guān)系,,對視圖的更新操作必須映射到對相應(yīng)的基本表操作才能實(shí)現(xiàn)。完成視圖更新后的數(shù)據(jù)庫狀態(tài)由視圖定義導(dǎo)出一個(gè)新的視圖狀態(tài),,新的視圖狀態(tài)對應(yīng)由原視圖狀態(tài)直接完成視圖的更新操作,。
如圖1所示,u是關(guān)系數(shù)據(jù)庫DB的視圖v(DB)的更新操作,,T(u)是對視圖更新操作的變換,,它作用到DB上產(chǎn)生新的數(shù)據(jù)庫狀態(tài)DB′、新的視圖狀態(tài)v(DB′),。正確的視圖更新操作使得u(v(DB))= v(DB′),。但是對視圖更新操作的變換T(u)并不總存在[6]。即使存在,,也不總是惟一的,。視圖的更新存在固有的歧義性,僅有上面的語義是不夠的,。
并且,,由于視圖本身的歧義性和語義不完整性[7],無法對于有著集合操作符(如:UNION,、MINUS等),、聚集函數(shù)(如:SUM、AVE等)和GROUP BY子句的視圖更新提供支持,。
2 Instead-Of觸發(fā)器設(shè)計(jì)實(shí)現(xiàn)
2.1 PL/SQL引擎體系結(jié)構(gòu)
根據(jù)PL/SQL語言兼有過程式語句和SQL語句的特點(diǎn),,GKD-Base PL/SQL引擎把過程式語句和SQL語句分開處理。為了降低引擎實(shí)現(xiàn)的復(fù)雜程度,,從功能性的角度將整個(gè)引擎劃分為前端編譯器和后端解釋執(zhí)行器" title="執(zhí)行器">執(zhí)行器,,每個(gè)處理模塊盡量降低相互間的耦合程度,。
前端編譯器包括語言預(yù)處理、SQL語句分析,、過程語句分析以及中間代碼生成等功能,。PL/SQL語句塊輸入后,由語言預(yù)處理功能分離成SQL語句和過程語句,。對于SQL語句,,由GKD-Base SQL引擎解析后,建立SQL語句結(jié)點(diǎn),,進(jìn)行相應(yīng)的變量綁定和語法檢查,,檢查無誤后產(chǎn)生語法樹形式的中間代碼。對于過程語句,,將語句成分進(jìn)行語法分析,,在分析中把聲明的變量和數(shù)據(jù)類型加入到名字空間和符號表中,同時(shí)產(chǎn)生語法樹形式的中間代碼,。
后端解釋執(zhí)行器的功能就是對前端編譯器生成的中間代碼進(jìn)行解釋執(zhí)行,。因此在結(jié)構(gòu)上,解釋執(zhí)行器與編譯器對應(yīng),,也有過程語句執(zhí)行模塊和SQL語句執(zhí)行模塊,,過程語句解釋執(zhí)行器解釋執(zhí)行過程語句的中間代碼,SQL命令則直接由SQL引擎執(zhí)行,。另外,,解釋器還包括例外處理模塊,負(fù)責(zé)檢查錯誤和報(bào)告錯誤[8],。
2.2 Instead-Of觸發(fā)器設(shè)計(jì)
2.2.1觸發(fā)器模型
GKD-Base DML觸發(fā)器采用傳統(tǒng)的ECA(Event-Condition-Action,,事件—條件—動作)規(guī)則設(shè)計(jì)。與之類似的Instead-Of 視圖觸發(fā)器也采用了ECA規(guī)則,。
為了適應(yīng)觸發(fā)器的具體情況,,在GKD-Base中,Instead-Of 視圖觸發(fā)器擴(kuò)展為一個(gè)四元組模型:Trigger:=
E(Event):激發(fā)Instead-Of 視圖觸發(fā)器的事件,。這里主要是指操作視圖的DML事件,包括Insert,、 Delete和Update等。
C(Condition):定義觸發(fā)器時(shí)指定的條件,。是一個(gè)一元謂詞表達(dá)式,。
A(Action):當(dāng)Event發(fā)生,并且Condition為真時(shí),觸發(fā)的動作,。
S(Status):觸發(fā)器有活躍和休眠兩種狀態(tài),,觸發(fā)器處于活躍狀態(tài)時(shí),才可被激發(fā),。
2.2.2 觸發(fā)器實(shí)現(xiàn)框架
觸發(fā)器實(shí)現(xiàn)框架如圖2所示,。觸發(fā)器類別判決器是在系統(tǒng)執(zhí)行SQL語句之前,對SQL語句的操作對象進(jìn)行判斷,,如果是對基本表操作,,則啟動DML觸發(fā)器的監(jiān)測功能;如果是對視圖進(jìn)行操作,則啟動Instead-Of 視圖觸發(fā)器的監(jiān)測功能,。事件監(jiān)視器是在有關(guān)的系統(tǒng)行為發(fā)生時(shí),,為各種預(yù)定的事件給觸發(fā)器調(diào)度器發(fā)送信號。觸發(fā)器調(diào)度器接收事件監(jiān)視器的信號,,從數(shù)據(jù)字典中獲取該事件點(diǎn)火的所有觸發(fā)器,,并且按照特定的順序排序,調(diào)用條件評價(jià)器檢查各觸發(fā)器的觸發(fā)條件是否滿足,,若滿足則由觸發(fā)器調(diào)度器通知PL/SQL引擎解釋執(zhí)行該觸發(fā)器的動作代碼,。條件評價(jià)器是用來檢查觸發(fā)條件是否滿足的部件。對于語句級觸發(fā)器,,由于不存在觸發(fā)條件子句,,所以觸發(fā)條件始終為真。對于行(元組)級觸發(fā)器,,條件評價(jià)器可以將其觸發(fā)條件WHEN子句轉(zhuǎn)換成一個(gè)PL/SQL語言的IF語句,,然后由PL/SQL引擎實(shí)現(xiàn)觸發(fā)器條件的計(jì)算。
2.3 Instead-Of觸發(fā)器實(shí)現(xiàn)
2.3.1 觸發(fā)器謂詞以及new和old元組的設(shè)計(jì)
觸發(fā)器謂詞是指觸發(fā)器內(nèi)部用來標(biāo)識激發(fā)觸發(fā)器動作的DML語句的布爾變量,,為:INSERTING,、UPDATING、DELETING,。其分別對應(yīng)于PL/SQL程序中的三個(gè)布爾變量,,它們在編譯觸發(fā)器時(shí)被加載到符號表中,在調(diào)用PL/SQL引擎執(zhí)行觸發(fā)器動作體之前,,它們的值被準(zhǔn)備好,,供PL/SQL引擎取用。
NEW和OLD元組作為PL/SQL程序中的記錄樣式加載到符號表中,,被編譯器引用,。其記錄域與新舊元組對應(yīng)的表的各個(gè)屬性一一對應(yīng)。在調(diào)用PL/SQL引擎執(zhí)行觸發(fā)器動作體之前,,必須準(zhǔn)備好NEW和OLD的值,。但NEW和OLD元組是偽記錄類型,,不能完全按照記錄的語法來訪問[12]。這一點(diǎn)必須在編譯時(shí)加入新的語義規(guī)則,。
2.3.2 Instead-Of觸發(fā)器的編譯與存儲
功能:編譯觸發(fā)器定義語句后,,將觸發(fā)器信息存儲于數(shù)據(jù)字典中。
輸入:一條用戶輸入的觸發(fā)器定義語句,。
輸出:觸發(fā)器數(shù)據(jù)字典的元組,。
(1)判斷當(dāng)前事務(wù)是否存在,如果存在,,則提交當(dāng)前事務(wù),,并開始一個(gè)新事務(wù);否則,,直接開始一個(gè)新事務(wù),。
(2)用戶權(quán)限檢查。如果當(dāng)前用戶無權(quán)執(zhí)行該操作,,轉(zhuǎn)(12),;否則轉(zhuǎn)(3)。
(3)檢查觸發(fā)表(視圖)名及觸發(fā)事件所涉及的屬性是否存在,。在GKD-Base的數(shù)據(jù)字典SYS.TABLES中查找,,如果觸發(fā)表或某個(gè)屬性不存在,轉(zhuǎn)(12),;否則,,轉(zhuǎn)(4)。
(4)觸發(fā)器名存在性檢查,。如果當(dāng)前定義的觸發(fā)器與以往定義的某個(gè)觸發(fā)器重名,,轉(zhuǎn)(5);否則轉(zhuǎn)(7),。
(5)如果聲明語句中沒有包含 OR REPLACE選項(xiàng),,轉(zhuǎn)(12);否則,,轉(zhuǎn)(6),。
(6)如果觸發(fā)表(視圖)不一致,轉(zhuǎn)(12),;否則轉(zhuǎn)(7)(觸發(fā)表指定義了DML觸發(fā)器或Instead-Of 視圖觸發(fā)器的基本表或視圖),。
(7)檢查定義觸發(fā)器的合法性,DML觸發(fā)器只能定義在基本表上,,而Instead-Of視圖觸發(fā)器只能定義在視圖上,。檢查合法,轉(zhuǎn)(8),,否則轉(zhuǎn)(12),。
(8)調(diào)用PL/SQL引擎編譯觸發(fā)器動作體,,并且將觸發(fā)器的WHEN條件子句轉(zhuǎn)換成一個(gè)IF語句,,這個(gè)IF語句的真值部分包括了觸發(fā)器動作體,。如果觸發(fā)器動作體中出現(xiàn)語法或語義錯誤,轉(zhuǎn)(12),;否則轉(zhuǎn)(9),。
(9)在數(shù)據(jù)字典SYS.TRIGGERS表中插入一個(gè)新元組,填入此觸發(fā)器的信息,。如果出現(xiàn)磁盤I/O錯誤,,轉(zhuǎn)(12);否則轉(zhuǎn)(10),。
(10)釋放所占資源,。
(11)提交當(dāng)前事務(wù),正常結(jié)束,。
(12)回滾當(dāng)前事務(wù),,報(bào)錯退出。
2.3.3 Instead-Of視圖觸發(fā)器的點(diǎn)火執(zhí)行
與DML觸發(fā)器不同,,Instead-Of 視圖觸發(fā)器在激發(fā)時(shí),,不必考慮各種觸發(fā)器(如語句級前觸發(fā)器和行級后觸發(fā)器)之間的相互纏結(jié)。其點(diǎn)火算法也相對簡單,。 在觸發(fā)事件當(dāng)前的事務(wù)中構(gòu)造一條SQL查詢語句,,從觸發(fā)器數(shù)據(jù)字典表中獲取與該觸發(fā)事件相關(guān)的處于活躍狀態(tài)的Instead-Of視圖觸發(fā)器元組。如果查詢結(jié)果不為空,,將觸發(fā)器條件轉(zhuǎn)換成一個(gè)PL/SQL語言的IF語句,,并將觸發(fā)事件當(dāng)前所用到的元組值(新值和舊值)準(zhǔn)備好,啟動PL/SQL引擎,,對觸發(fā)器動作體的源代碼進(jìn)行解釋執(zhí)行,。釋放所占的資源,結(jié)束觸發(fā)器調(diào)用,。
3 系統(tǒng)應(yīng)用實(shí)例
3.1實(shí)驗(yàn)數(shù)據(jù)
Rooms表如表1所示,,Classes表如表2所示。在Classes表和Rooms表中Room_ID相等的連接條件上創(chuàng)建一個(gè)名為Classes_rooms的視圖,,進(jìn)行連接運(yùn)算,。Classes_rooms視圖如表3所示。
定義關(guān)于Classes_rooms 的Update語義:通過對Classes_rooms的Update操作,,實(shí)現(xiàn)對一個(gè)班級某門課程占用教室的調(diào)整,。通過Instead-Of觸發(fā)器實(shí)現(xiàn):如果修改了Classes_rooms的Dept和Course屬性,那么就修改Classes基本表的相應(yīng)屬性,,如果修改了Classes_rooms的Building和Room_Num屬性,,那么就修改Rooms基本表的相應(yīng)屬性,。再適當(dāng)調(diào)整兩個(gè)基本表的Room_ID。
3.2 實(shí)驗(yàn)結(jié)果
執(zhí)行UPDATE classes_rooms SET Dept=‘NUT’, course = 307 WHERE building=‘Buidling 7’ AND room_num = 201; 查詢更新后的視圖,,觀察Instead-Of觸發(fā)器對視圖的作用,。
表4、表5,、表6演示了本實(shí)驗(yàn)的結(jié)果,。由結(jié)果可知,通過Instead-Of觸發(fā)器,,成功地對Classes_rooms視圖進(jìn)行了修改,,將歷史系101課的教室調(diào)整給了營養(yǎng)系307課程使用。通過以上應(yīng)用實(shí)例驗(yàn)證了Instead-Of觸發(fā)器帶給數(shù)據(jù)庫系統(tǒng)的視圖修改功能,。
本文參照Oracle PL/SQL V2.3 語言規(guī)范,,在數(shù)據(jù)庫管理系統(tǒng)GKD-Base 的PL/SQL引擎的基礎(chǔ)上,給出了Instead-Of 視圖觸發(fā)器的編譯存儲和點(diǎn)火執(zhí)行的相關(guān)算法,,設(shè)計(jì)了Instead-Of視圖觸發(fā)器編譯及執(zhí)行處理模塊,,從而在實(shí)現(xiàn)DML 觸發(fā)器的基礎(chǔ)上實(shí)現(xiàn)了Instead-Of 視圖觸發(fā)器,并在實(shí)際中得到了驗(yàn)證,。擴(kuò)展了GKD-Base的功能,,使其能夠應(yīng)用于更多的領(lǐng)域。
參考文獻(xiàn)
1 Tom Portfolio. PL/SQL User′s Guide and Reference. Release 8.1.6. Oracle Corporation,1999
2 Ken Henderson. The Guru′s Guide to Transact-SQL. AddisonWesley Pub Co., 2000;2
3 PostgreSQL 7.4 Documentation.The PostgreSQL Global Development Group, 2003
4 景 寧. SQL查詢處理與實(shí)現(xiàn)技術(shù)研究.長沙:國防科技大學(xué).工學(xué)博士學(xué)位論文,1990;4
5 E.F.Codd. Recent Investigations in a Relational Database System. North-Holland Publishing Company,1974
6 劉念祖. 數(shù)據(jù)庫系統(tǒng)中視圖問題的研究. 計(jì)算機(jī)工程,1997;12
7 陳火旺. 程序設(shè)計(jì)語言——編譯原理.北京:國防工業(yè)出版社,,2000