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