觸發器的學習
觸發器使用教程和命名規範
目 錄
觸發器使用教程和命名規範 1
1,觸發器簡介 1
2,觸發器示例 2
3,觸發器語法和功能 3
4,例一:行級觸發器之一 4
5,例二:行級觸發器之二 4
6,例三:INSTEAD OF觸發器 6
7,例四:語句級觸發器之一 8
8,例五:語句級觸發器之二 9
9,例六:用包封裝觸發器程式碼 10
10,觸發器命名規範 11
1,觸發器簡介
觸發器(Trigger)是資料庫物件的一種,編碼方式類似儲存過程,與某張表(Table)相關聯,當有DML語句對錶進行操作時,可以引起觸發器的執行,達到對插入記錄一致性,正確性和規範性控制的目的。在當年C/S時代盛行的時候,由於客戶端直接連線資料庫,能保證資料庫一致性的只有資料庫本身,此時主鍵(Primary Key),外來鍵(Foreign Key),約束(Constraint)和觸發器成為必要的控制機制。而觸發器的實現比較靈活,可程式設計性強,自然成為了最流行的控制機制。到了B/S時代,發展成4層架構,客戶端不再能直接訪問資料庫,只有中介軟體才可以訪問資料庫。要控制資料庫的一致性,既可以在中介軟體裡控制,也可以在資料庫端控制。很多的青睞Java的開發者,隨之將資料庫當成一個黑盒,把大多數的資料控制工作放在了Servlet中執行。這樣做,不需要了解太多的資料庫知識,也減少了資料庫程式設計的複雜性,但同時增加了Servlet程式設計的工作量。從架構設計來看,中介軟體的功能是檢查業務正確性和執行業務邏輯,如果把資料的一致性檢查放到中介軟體去做,需要在所有涉及到資料寫入的地方進行資料一致性檢查。由於資料庫訪問相對於中介軟體來說是遠端呼叫,要編寫統一的資料一致性檢查程式碼並非易事,一般採用在多個地方的增加類似的檢查步驟。一旦一致性檢查過程發生調整,勢必導致多個地方的修改,不僅增加工作量,而且無法保證每個檢查步驟的正確性。觸發器的應用,應該放在關鍵的,多方發起的,高頻訪問的資料表上,過多使用觸發器,會增加資料庫負擔,降低資料庫效能。而放棄使用觸發器,則會導致系統架構設計上的問題,影響系統的穩定性。
2,觸發器示例
觸發器程式碼類似儲存過程,以PL/SQL指令碼編寫。下面是一個觸發器的示例:
新建員工工資表salary
create table SALARY
(
EMPLOYEE_ID NUMBER, –員工ID
MONTH VARCHAR2(6), –工資月份
AMOUNT NUMBER –工資金額
)
建立與salary關聯的觸發器salary_trg_rai
1 Create or replace trigger salary_trg_rai
2 After insert on salary
3 For each row
4 declare
5 Begin
6 Dbms_output.put_line(‘員工ID:’ || :new.employee_id);
7 Dbms_output.put_line(‘工資月份:’ || :new.month);
8 Dbms_output.put_line(‘工資:’ || :new.amount);
9 Dbms_output.put_line(‘觸發器已被執行’);
10 End;
開啟一個SQL Window視窗(使用PL/SQL Developer工具),或在sqlplus中輸入:
Insert into salary(employee_id, month, amount) values(1, ‘200606’, 10000);
執行後可以在sqlplus中,或在SQL Window視窗的Output中見到
員工ID:1
工資月份:200606
工資:10000
觸發器已執行
在程式碼的第一行,定義了資料庫物件的型別是trigger,定義觸發器的名稱是salary_trg_rai
第二行說明了這是一個after觸發器,在DML操作實施之後執行。緊接著的insert說明了這是一個針對insert操作的觸發器,每個對該表進行的insert操作都會執行這個觸發器。
第三行說明了這是一個針對行級的觸發器,當插入的記錄有n條時,在每一條插入操作時都會執行該觸發器,總共執行n次。
Declare後面跟的是本地變數定義部分,如果沒有本地變數定義,此部分可以為空
Begin和end括起來的程式碼,是觸發器的執行部分,一般會對插入記錄進行一致性檢查,在本例中列印了插入的記錄和“觸發器已執行”。
其中:new物件表示了插入的記錄,可以通過:new.column_name來引用記錄的每個欄位值
3,觸發器語法和功能
觸發器的語法如下
CREATE OR REPLACE TRIGGER trigger_name
<before | after | instead of> <insert | update | delete> ON table_name
[FOR EACH ROW]
WHEN (condition)
DECLARE
BEGIN
--觸發器程式碼
END;
Trigge
r_name是觸發器的名稱。
<before | after | instead of>
可以選擇before或者after或instead of。Before表示在DML語句實施前執行觸發器,而after表示在在dml語句實施之後執行觸發器,instead of觸發器用在對檢視的更新上。<insert | update | delete>
:insert or update。Table_name是觸發器關聯的表名。
[FOR EACH ROW]為可選項,如果註明了FOR EACH ROW,則說明了該觸發器是一個行級的觸發器,DML語句處理每條記錄都會執行觸發器;否則是一個語句級的觸發器,每個DML語句觸發一次。
WHEN後跟的condition是觸發器的響應條件,只對行級觸發器有效,當操作的記錄滿足condition時,觸發器才被執行,否則不執行。Condition中可以通過new物件和old物件(注意區別於前面的:new和:old,在程式碼中引用需要加上冒號)來引用操作的記錄。
觸發器程式碼可以包括三種類型:未涉及資料庫事務程式碼,涉及關聯表(上文語法中的table_name)資料庫事務程式碼,涉及除關聯表之外資料庫事務程式碼。其中第一種型別程式碼只對資料進行簡單運算和判斷,沒有DML語句,這種型別程式碼可以在所有的觸發器中執行。第二種型別程式碼涉及到對關聯表的資料操作,比如查詢關聯表的總記錄數或者往關聯表中插入一條記錄,該型別程式碼只能在語句級觸發器中使用,如果在行級觸發器中使用,將會報ORA-04091錯誤。第三種類型程式碼涉及到除關聯表之外的資料庫事務,這種程式碼可以在所有觸發器中使用。
從觸發器的功能上來看,可以分成3類:
重寫列(僅限於before觸發器)
採取行動(任何觸發器)
拒絕事務(任何觸發器)
“重寫列”用於對錶欄位的校驗,當插入值為空或者插入值不符合要求,則觸發器用預設值或另外的值代替,在多數情況下與欄位的default屬性相同。這種功能只能在行級before觸發器中執行。“採取行動”針對當前事務的特點,對相關表進行操作,比如根據當前表插入的記錄更新其他表,銀行中的總帳和分戶帳間的總分關係就可以通過這種觸發器功能來維護。“拒絕事務”用在對資料的合法性檢驗上,當更新的資料不滿足表或系統的一致性要求,則通過丟擲異常的方式拒絕事務,在其上層的程式碼可以捕獲這個異常並進行相應操作。
下面將通過舉例說明,在例子中將觸發器主體的語法一一介紹,讀者可以在例子中體會觸發器的功能。