觸發(fā)器是存儲(chǔ)程序,它會(huì)自動(dòng)執(zhí)行或發(fā)射當(dāng)一些事件發(fā)生。觸發(fā)器,事實(shí)上,寫(xiě)入響應(yīng)于以下任一事件將被執(zhí)行:
數(shù)據(jù)庫(kù)操作(DML)語(yǔ)句(DELETE,INSERT,UPDATE或)
數(shù)據(jù)庫(kù)定義(DDL)語(yǔ)句(CREATE,ALTER或DROP)
數(shù)據(jù)庫(kù)操作(SERVERERROR,登錄,注銷(xiāo),啟動(dòng)或關(guān)機(jī))
觸發(fā)器可以在表,視圖,模式或數(shù)據(jù)庫(kù)與該事件相關(guān)聯(lián)上定義
觸發(fā)器可以用于以下目的寫(xiě):
自動(dòng)生成一些派生列值
實(shí)施參照完整性
事件日志和對(duì)表的訪問(wèn)存儲(chǔ)信息
審計(jì)
表的同步復(fù)制
實(shí)行安全許可
防止非法交易
創(chuàng)建觸發(fā)器的語(yǔ)法:
CREATE [OR REPLACE ] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF } {INSERT [OR] | UPDATE [OR] | DELETE} [OF col_name] ON table_name [REFERENCING OLD AS o NEW AS n] [FOR EACH ROW] WHEN (condition) DECLARE Declaration-statements BEGIN Executable-statements EXCEPTION Exception-handling-statements END;
那么,
CREATE [OR REPLACE] TRIGGER trigger_name: 創(chuàng)建或替換現(xiàn)有的觸發(fā)器:trigger_name
{BEFORE | AFTER | INSTEAD OF} : 指定當(dāng)觸發(fā)將被執(zhí)行。在INSTEAD OF子句用于在視圖中創(chuàng)建觸發(fā)器
{INSERT [OR] | UPDATE [OR] | DELETE}: 指定DML操作
[OF col_name]: 指定將被更新的列名
[ON table_name]: 指定觸發(fā)器相關(guān)聯(lián)的表的名稱(chēng)
[REFERENCING OLD AS o NEW AS n]: 可以參考新舊值的各種DML語(yǔ)句,如INSERT,UPDATE和DELETE
[FOR EACH ROW]: 指定的行級(jí)觸發(fā)器,即觸發(fā)器將每一行受到影響執(zhí)行。否則,當(dāng)執(zhí)行SQL語(yǔ)句,這被稱(chēng)為表級(jí)觸發(fā)器觸發(fā)將執(zhí)行一次
WHEN (condition): 觸發(fā)器將觸發(fā)的條件。此子句僅適用于行級(jí)觸發(fā)器有效
首先,將使用我們已經(jīng)創(chuàng)建,并在前面的章節(jié)中使用的CUSTOMERS表:
Select * from customers; +----+----------+-----+-----------+----------+ | ID | NAME | AGE | ADDRESS | SALARY | +----+----------+-----+-----------+----------+ | 1 | Ramesh | 32 | Ahmedabad | 2000.00 | | 2 | Khilan | 25 | Delhi | 1500.00 | | 3 | kaushik | 23 | Kota | 2000.00 | | 4 | Chaitali | 25 | Mumbai | 6500.00 | | 5 | Hardik | 27 | Bhopal | 8500.00 | | 6 | Komal | 22 | MP | 4500.00 | +----+----------+-----+-----------+----------+
下面的程序創(chuàng)建了customers表中,將觸發(fā)INSERT或UPDATE或DELETE在Customers表進(jìn)行操作的行級(jí)觸發(fā)。觸發(fā)器將顯示工資的舊值和新值之間的差額:
CREATE OR REPLACE TRIGGER display_salary_changes BEFORE DELETE OR INSERT OR UPDATE ON customers FOR EACH ROW WHEN (NEW.ID > 0) DECLARE sal_diff number; BEGIN sal_diff := :NEW.salary - :OLD.salary; dbms_output.put_line('Old salary: ' || :OLD.salary); dbms_output.put_line('New salary: ' || :NEW.salary); dbms_output.put_line('Salary difference: ' || sal_diff); END; /
當(dāng)上述代碼在SQL提示符執(zhí)行時(shí),它產(chǎn)生了以下結(jié)果:
Trigger created.
這里以下兩點(diǎn)是重要的,應(yīng)小心注意:
OLD和NEW引用是不可用于表級(jí)觸發(fā)器,而不可以使用它們的創(chuàng)紀(jì)錄級(jí)別的觸發(fā)器。
如果想查詢(xún)表中相同的觸發(fā),那么應(yīng)用應(yīng)該使用AFTER關(guān)鍵字,因?yàn)橛|發(fā)器可以查詢(xún)?cè)摫?,或再次改變它最初的變化僅適用后的表是回到一致的狀態(tài)。
上述觸發(fā)已經(jīng)寫(xiě)在這樣一種方式,它會(huì)在任何DELETE、INSERT或UPDATE操作在表上之前執(zhí)行,但可以?shī)Z觸發(fā)器上編寫(xiě)一個(gè)或多個(gè)操作,例如BEFORE DELETE,這將會(huì)觸發(fā)每當(dāng)一個(gè)記錄將使用在表上刪除操作被刪除。
讓我們?cè)贑USTOMERS表執(zhí)行某些DML操作。這里有一個(gè)INSERT語(yǔ)句,這將在表中創(chuàng)建一個(gè)新的記錄:
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (7, 'Kriti', 22, 'HP', 7500.00 );
當(dāng)記錄在CUSTOMERS表中創(chuàng)建,上面創(chuàng)建觸發(fā)器display_salary_changes將被觸發(fā),它會(huì)顯示以下結(jié)果:
Old salary: New salary: 7500 Salary difference:
因?yàn)檫@是一個(gè)新的記錄,因此基本工資不可用及以上的結(jié)果來(lái)為空(null)?,F(xiàn)在,讓我們對(duì)CUSTOMERS表進(jìn)行多一個(gè)DML操作。這里有一個(gè)UPDATE語(yǔ)句,該語(yǔ)句將更新表中現(xiàn)有的記錄:
UPDATE customers SET salary = salary + 500 WHERE id = 2;
當(dāng)記錄在CUSTOMERS表更新,上面創(chuàng)建觸發(fā)器display_salary_changes將被觸發(fā),它會(huì)顯示以下結(jié)果:
Old salary: 1500 New salary: 2000 Salary difference: 500