轉眼,從實習到畢業,來公司已經差不多有4個月了。在學校沒學到什麼東西,怪自己太懶,又沒有鑽研技術的那股精神。如今來公司做金蝶系列的插件開發,都顯得很吃力。 之前在學校,資料庫就學了一點毛皮,現在要學會寫SQL存儲過程,觸發器,報表等高級SQL查詢語句,下麵給出自己學習寫觸發器的過程: 什麼是觸發器, ...
轉眼,從實習到畢業,來公司已經差不多有4個月了。在學校沒學到什麼東西,怪自己太懶,又沒有鑽研技術的那股精神。如今來公司做金蝶系列的插件開發,都顯得很吃力。
之前在學校,資料庫就學了一點毛皮,現在要學會寫SQL存儲過程,觸發器,報表等高級SQL查詢語句,下麵給出自己學習寫觸發器的過程:
什麼是觸發器,從網上搜了一大堆資料後,總結如下:
觸發器,顧名思義,通過觸發來引發的一種執行語句。其實觸發器也是一種特殊的存儲過程,一般的存儲過程是通過存程名直接調用,而觸發器是通過事件進行觸發而執行的。這是一個什麼樣的事件呢?主要分為增,刪,改之類的執行事件 。當表中的數據發生變化時自動強制執行。常見的觸發器有兩種:
after(for) 表示執行代碼後,執行觸發器
instead of 表示執行代碼前,用已經寫好的觸發器代替你的操作
觸發器語法:
create trigger 觸發器的名字 on 操作表
for|after instead of
update|insert|delete
as
SQL語句
觸發器實現原理圖
其中after觸發器要求只有執行某一操作insert、update、delete之後觸發器才被觸發,且只能定義在表上。而instead of觸發器表示並不執行其定義的操作(insert、update、delete)而僅是執行觸發器本身。既可以在表上定義instead of觸發器,也可以在視圖上定義。
觸發器有兩個特殊的表:插入表(instered表)和刪除表(deleted表)。這兩張是邏輯表也是虛表。有系統在記憶體中創建者兩張表,不會存儲在資料庫中。而且兩張表的都是只讀的,只能讀取數據而不能修改數據。這兩張表的結果總是與被改觸發器應用的表的結構相同。當觸發器完成工作後,這兩張表就會被刪除。Inserted表的數據是插入或是修改後的數據,而deleted表的數據是更新前的或是刪除的數據。
對錶的操作 |
Inserted邏輯表 |
Deleted邏輯表 |
增加記錄(insert) |
存放增加的記錄 |
無 |
刪除記錄(delete) |
無 |
存放被刪除的記錄 |
修改記錄(update) |
存放更新後的記錄 |
存放更新前的記錄 |
Update數據的時候就是先刪除表記錄,然後增加一條記錄。這樣在inserted和deleted表就都有update後的數據記錄了。註意的是:觸發器本身就是一個事務,所以在觸發器裡面可以對修改數據進行一些特殊的檢查。如果不滿足可以利用事務回滾,撤銷操作。
觸發器示例
Example1
--禁止用戶插入數據(實際上是先插入,然後立刻將其刪除!)
create trigger tr_insert on bank
for --for表示執行之後的操作
insert --即先執行了插入操作,同時在臨時表中保存了插入記錄
as
--執行完插入之後,在新生成的表中將剛剛插入的那條記錄刪除,
--而此時得到的剛剛插入的記錄的id是通過臨時表 inserted得到的
delete * from bank where cid=(select cid from inserted)
生成上面的觸發器後,當用戶再輸入insert語句後就見不到效果了!
如:insert into bank values('0004',10000),是插入不進資料庫的。
Example2
--刪除誰就讓誰的賬戶加上10元
create trigger tr_dalete on bank
instead of
delete
as
update bank balance=balance+10 where cid=(select cid from deleted)
生成這個觸發器之後,當用戶輸入delete語句後,對應的那個id不但沒有被刪除掉,而且他的賬戶增加了10元
如:delete from bank where cid='0002',執行完這句話後,編號為0002的賬戶會增加10元
經典案例eg:
觸發器的簡單實例
eg:禁止插入新的數據的觸發器(先插入,再刪除)
CREATE TRIGGER tr_insert ON scorerecord
FOR (after)
INSERT
AS
DELETE FROM scorerecord WHERE id =(SELECT id FROM inserted)
測試SQL語句 : INSERT INTO scorerecord VALUES('1018','1306','c#編程','98')
eg2:
CREATE TRIGGER tr_insert2 ON usertest
AFTER
INSERT
AS
DELETE FROM usertest WHERE Id_P =(SELECT Id_P FROM INSERTED)
測試SQL語句:INSERT INTO usertest(Id_P,Lastname,Firstname) VALUES('3','習大大','琢磨')
刪除時候,自動加10分
eg1:
CREATE TRIGGER tr_delete ON scorerecord
INSTEAD OF
DELETE
as
UPDATE scorerecord SET score = score + 10 WHERE id = (SELECT id FROM deleted)
測試SQL語句:DELETE FROM dbo.scorerecord WHERE id = '26'
eg2:
CREATE TRIGGER tr_delete2 ON usertest
INSTEAD OF
DELETE
as
UPDATE usertest SET score = score+19 WHERE Id_P =(SELECT Id_P FROM deleted )
測試SQL語句:DELETE FROM usertest WHERE Id_P ='1'
另外測試:
--觸發器的案例
--創建觸發器
CREATE TRIGGER tr_mytrigger ON testdate2
AFTER UPDATE
as PRINT 'the table was update!'
--測試
UPDATE testdate2 SET Course = '歷史' WHERE Course ='英語'
--修改觸發器
ALTER TRIGGER tr_mytrigger ON testdate2
FOR UPDATE
as PRINT '一定要學會用觸發器'
--測試
UPDATE testdate2 SET Score = Score + 60 WHERE username ='小明'
SELECT * FROM dbo.testdate2
--查看觸發器內容
EXEC sp_helptext tr_mytrigger
--查詢資料庫中有多少觸發器
SELECT * FROM sysobjects WHERE xtype ='tr'
select * from sys.triggers --查詢資料庫中觸發器的名字 當不知道觸發器名字的時候
select * from sysobjects where type='tr' and name='tr_mytrigger' --知道觸發器的名字
--禁用觸發器
DISABLE TRIGGER tr_mytrigger ON testdate2
--啟用觸發器
ENABLE TRIGGER tr_mytrigger ON testdate2
--觸發器功能比較強大,但是一旦觸發,恢復起來比較麻煩,那我們就需要對數據進行保護,這裡需要用到rollback數據回滾
ALTER TRIGGER tr_mytrigger ON testdate2
AFTER UPDATE
as
IF EXISTS(SELECT * FROM testdate2 WHERE Score='156')
ROLLBACK
--測試
UPDATE testdate2 SET Score ='97' WHERE Score = '82' --有數據保護,觸發器中止