SQL Server編程(06)觸發器


SQL Server 通過觸發器用來保證業務邏輯和數據的完整性。在SQL Server中,觸發器是一種特殊類型的存儲過程,可在執行語言事件時自動觸發。SQL Server中觸發器包括三種:DML觸發器、DDL觸發器和登錄觸發器。

  • DML觸發器:執行DML語句觸發執行,例如操作數據表或視圖的insert、update、delete語句,不包含select。
  • DDL觸發器:執行DDL語句時觸發執行,例如create table等語句。
  • 登錄觸發器:在用戶登錄SQL Server實例創建會話時觸發。

SQL Server將觸發器和觸發它的語句放在一個可回滾事務中,如果觸發器發生異常,則與該觸發器相關的語句自動回滾。

DML的功能(優點):

  • 實現表的級聯更改,實現與外鍵約束相似的功能(如果外鍵可以約束,則不推薦使用觸發器)
  • 防止惡意或錯誤的insert、update、delete操作。觸發器比check約束更加強大,觸發器可以引用其它數據表,執行更加復雜的限制,而check約束不能引用其它表。
  • 可以獲取到更改前和修改后的數據,根據差異采取措施,決定是commit,還是rollback
  • 一個表支持創建多個同類型的DML觸發器

注意:有日志操作的行為才會激活觸發器。例如truncate table刪除表中所有數據,并沒有執行日志操作,所以不會激活delete觸發器。

創建觸發器

DML觸發器分為:

  • after觸發器(之后觸發)
    1. insert觸發器
    2. update觸發器
    3. delete觸發器
  • instead of 觸發器 (之前觸發)

其中after觸發器要求只有執行某一操作insert、update、delete之后觸發器才被觸發,且只能定義在表上。而instead of觸發器表示并不執行其定義的操作(insert、update、delete)而僅是執行觸發器本身。既可以在表上定義instead of觸發器,也可以在視圖上定義。

觸發器有兩個特殊的表:插入表(instered表)和刪除表(deleted表)。這兩張是邏輯表也是虛表。有系統在內存中創建者兩張表,不會存儲在數據庫中。而且兩張表的都是只讀的,只能讀取數據而不能修改數據。這兩張表的結果總是與被改觸發器應用的表的結構相同。當觸發器完成工作后,這兩張表就會被刪除。Inserted表的數據是插入或是修改后的數據,而deleted表的數據是更新前的或是刪除的數據。

?Inserted邏輯表Deleted邏輯表
增加記錄(insert)存放增加的記錄
刪除記錄(delete)存放被刪除的記錄
修改記錄(update)存放更新后的記錄存放更新前的記錄

Update數據的時候就是先刪除表記錄,然后增加一條記錄。這樣在inserted和deleted表就都有update后的數據記錄了。注意的是:觸發器本身就是一個事務,所以在觸發器里面可以對修改數據進行一些特殊的檢查。如果不滿足可以利用事務回滾,撤銷操作。

創建觸發器的語法:

create trigger tgr_name
on table_name
with encrypion 加密觸發器for update...
asTransact-SQL

?

創建insert類型觸發器

insert觸發器,會在inserted表中添加一條剛插入的記錄。

--創建insert插入類型觸發器
if (object_id('tgr_classes_insert', 'tr') is not null)drop trigger tgr_classes_insert
go
create trigger tgr_classes_insert
on classesfor insert --插入觸發
as--定義變量declare @id int, @name varchar(20), @temp int;--在inserted表中查詢已經插入記錄信息select @id = id, @name = name from inserted;set @name = @name + convert(varchar, @id);set @temp = @id / 2;    insert into student values(@name, 18 + @id, @temp, @id);print '添加學生成功!';
go
--插入數據
insert into classes values('5班', getDate());
--查詢數據
select * from classes;
select * from student order by id;

?

創建delete類型觸發器

delete觸發器會在刪除數據的時候,將剛才刪除的數據保存在deleted表中。

--delete刪除類型觸發器
if (object_id('tgr_classes_delete', 'TR') is not null)drop trigger tgr_classes_delete
go
create trigger tgr_classes_delete
on classesfor delete --刪除觸發
asprint '備份數據中……';    if (object_id('classesBackup', 'U') is not null)--存在classesBackup,直接插入數據insert into classesBackup select name, createDate from deleted;else--不存在classesBackup創建再插入select * into classesBackup from deleted;print '備份數據成功!';
go
--
--不顯示影響行數
--set nocount on;
delete classes where name = '5班';
--查詢數據
select * from classes;
select * from classesBackup;

?

創建update類型觸發器

update觸發器會在更新數據后,將更新前的數據保存在deleted表中,更新后的數據保存在inserted表中。

--update更新類型觸發器
if (object_id('tgr_classes_update', 'TR') is not null)drop trigger tgr_classes_update
go
create trigger tgr_classes_update
on classesfor update
asdeclare @oldName varchar(20), @newName varchar(20);--更新前的數據select @oldName = name from deleted;if (exists (select * from student where name like '%'+ @oldName + '%'))begin--更新后的數據select @newName = name from inserted;update student set name = replace(name, @oldName, @newName) where name like '%'+ @oldName + '%';print '級聯修改數據成功!';endelseprint '無需修改student表!';
go
--查詢數據
select * from student order by id;
select * from classes;
update classes set name = '五班' where name = '5班';

?

update更新列級觸發器

更新列級觸發器可以用update是否判斷更新列記錄;

if (object_id('tgr_classes_update_column', 'TR') is not null)drop trigger tgr_classes_update_column
go
create trigger tgr_classes_update_column
on classesfor update
as--列級觸發器:是否更新了班級創建時間if (update(createDate))beginraisError('系統提示:班級創建時間不能修改!', 16, 11);rollback tran;end
go
--測試
select * from student order by id;
select * from classes;
update classes set createDate = getDate() where id = 3;
update classes set name = '四班' where id = 7;

instead of 類型觸發器

instead of 觸發器表示并不執行其定義的操作(insert、update、delete)而僅是執行觸發器本身的內容。

語法:

create trigger tgr_name
on table_name
with encryptioninstead of update...
asT-SQL

創建instead of觸發器

if (object_id('tgr_classes_inteadOf', 'TR') is not null)drop trigger tgr_classes_inteadOf
go
create trigger tgr_classes_inteadOf
on classesinstead of delete/*, update, insert*/
asdeclare @id int, @name varchar(20);--查詢被刪除的信息,病賦值select @id = id, @name = name from deleted;print 'id: ' + convert(varchar, @id) + ', name: ' + @name;--先刪除student的信息delete student where cid = @id;--再刪除classes的信息delete classes where id = @id;print '刪除[ id: ' + convert(varchar, @id) + ', name: ' + @name + ' ] 的信息成功!';
go
--test
select * from student order by id;
select * from classes;
delete classes where id = 7;

顯示錯誤信息(raiserror)

if (object_id('tgr_message', 'TR') is not null)drop trigger tgr_message
go
create trigger tgr_message
on studentafter insert, update
as raisError('tgr_message觸發器被觸發', 16, 10);
go
--test
insert into student values('lily', 22, 1, 7);
update student set sex = 0 where name = 'lucy';
select * from student order by id;

修改觸發器

alter trigger tgr_message
on student
after delete
as raisError('tgr_message觸發器被觸發', 16, 10);
go
--test
delete from student where name = 'lucy';

?

啟用、禁用觸發器

--禁用觸發器
disable trigger tgr_message on student;
--啟用觸發器
enable trigger tgr_message on student;

?

查詢創建的觸發器信息

--查詢已存在的觸發器
select * from sys.triggers;
select * from sys.objects where type = 'TR';--查看觸發器觸發事件
select te.* from sys.trigger_events te join sys.triggers t
on t.object_id = te.object_id
where t.parent_class = 0 and t.name = 'tgr_valid_data';--查看創建觸發器語句
exec sp_helptext 'tgr_message';

?

示例,驗證插入數據

if ((object_id('tgr_valid_data', 'TR') is not null))drop trigger tgr_valid_data
go
create trigger tgr_valid_data
on student
after insert
asdeclare @age int,@name varchar(20);select @name = s.name, @age = s.age from inserted s;if (@age < 18)beginraisError('插入新數據的age有問題', 16, 1);rollback tran;end
go
--test
insert into student values('forest', 2, 0, 7);
insert into student values('forest', 22, 0, 7);
select * from student order by id;

示例,操作日志

if (object_id('log', 'U') is not null)drop table log
go
create table log(id int identity(1, 1) primary key,action varchar(20),createDate datetime default getDate()
)
go
if (exists (select * from sys.objects where name = 'tgr_student_log'))drop trigger tgr_student_log
go
create trigger tgr_student_log
on student
after insert, update, delete
asif ((exists (select 1 from inserted)) and (exists (select 1 from deleted)))begininsert into log(action) values('updated');endelse if (exists (select 1 from inserted) and not exists (select 1 from deleted))begininsert into log(action) values('inserted');endelse if (not exists (select 1 from inserted) and exists (select 1 from deleted))begininsert into log(action) values('deleted');end
go
--test
insert into student values('king', 22, 1, 7);
update student set sex = 0 where name = 'king';
delete student where name = 'king';
select * from log;
select * from student order by id;本文轉自齊師傅博客園博客,原文鏈接:http://www.cnblogs.com/youring2/p/4929149.html,如需轉載請自行聯系原作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279164.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279164.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279164.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網站運行java_定制化Azure站點Java運行環境(5)

Java 8下PermGen及參數設置在上一章節中&#xff0c;我們定制化使用了Java 8環境&#xff0c;使用我們的測試頁面打印出了JVM基本參數&#xff0c;但如果我們自己觀察&#xff0c;會發現在MXBeans中&#xff0c;沒有出現PermGen的使用數據&#xff0c;初始大小等信息&#xff0…

三階魔方魔方公式_觀看此魔方的自我解決

三階魔方魔方公式Finally: a Rubik’s cube that can solve itself. A maker named Human Controller built it in Japan, and you can see it in action right now. 最后&#xff1a;一個可以解決自身問題的魔方。 一家名為Human Controller的制造商在日本制造了它&#xff0…

pc樣式在ie8中的bug

2019獨角獸企業重金招聘Python工程師標準>>> pc樣式在ie8中的bug 1,box-sizing:border-box: 在ie中,此屬性的使用有限制: (在IE8中&#xff0c;min-width屬性適用于content-box即使box-sizing設置為border-box。 Chrome select在使用時從元素中選擇選項時遇到問…

下載: 蝦米音樂_您所說的內容:如何組織凌亂的音樂收藏

下載: 蝦米音樂Earlier this week we asked you to share your tips, tricks, and tools, for managing a messy music collection. Now we’re back to share so great reader tips; read on to find ways to tame your mountain of music. 本周早些時候&#xff0c;我們要求您…

Django form表單

Django form表單 目錄 普通方式手寫注冊功能 views.pylogin.html使用form組件實現注冊功能 views.pylogin2.html常用字段與插件 initialerror_messagespasswordradioSelect單選Select多選Select單選checkbox多選checkboxDjango Form所有內置字段校驗補充進階 應用Bootstrap樣式…

java 多線程 優先級_java多線程之線程的優先級

在操作系統中&#xff0c;線程可以劃分優先級&#xff0c;優先級較高的線程得到CPU資源較多&#xff0c;也就是CPU優先執行優先級較高的線程對象中的任務(其實并不是這樣)。在java中&#xff0c;線程的優先級用setPriority()方法就行&#xff0c;線程的優先級分為1-10這10個等級…

PyQt5應用與實踐

2015-01-16 19:00 by 吳秦, 69476 閱讀, 5 評論, 收藏, 編輯 一個典型的GUI應用程序可以抽象為&#xff1a;主界面&#xff08;菜單欄、工具欄、狀態欄、內容區域&#xff09;&#xff0c;二級界面&#xff08;模態、非模態&#xff09;&#xff0c;信息提示&#xff08;Toolti…

plex實現流媒體服務器_Plex繼續遠離服務器,提供網絡節目

plex實現流媒體服務器() Plex now offers a “Web Shows” feature in certain versions of their interface, providing access to shows from brands like TWiT, GQ, and Popular Science. Plex現在在其界面的某些版本中提供了“網絡節目”功能&#xff0c;可以訪問TWiT&…

MIME協議(三) -- MIME郵件的組織結構

一封MIME郵件可以由多個不同類型的MIME消息組合而成&#xff0c;一個MIME消息表示郵件中的一個基本MIME資源或若干基本MIME消息的組合體。每個MIME消息的數據格式與RFC822數據格式相似&#xff0c;也包括頭和體兩部分&#xff0c;分別稱為MIME消息頭和MIME消息體&#xff0c;它…

discord linux_最好的Discord機器人來啟動服務器

discord linuxDiscord has an extensive API and good support for bots on their platform. Because of this, there are tons of bots to go around. However, many of them just copy one another’s functionality. We’ve picked out the ones that do it right, and comp…

java獲取前端json數據_java如何獲取前端ajax傳來的json對象

假設使用 jQuery 中的 ajax1. Json 對象前端代碼示例$.ajax({url : http://localhost:8888/demo,type: post,data: {userName:15488779956}success: function(data) {// TODO}})后臺代碼示例RestControllerpublic class Demo {/*** 方法 1 使用 HttpServletRequest 接收* */Req…

版本控制介紹以及常用的版本控制工具

版本控制是指對軟件開發過程中各種程序代碼、配置文件及說明文檔等文件變更的管理&#xff0c;是軟件配置管理的核心思想之一。 編寫一個成熟可用的程序是一個工作量很大的工程&#xff0c;并非我們一次性就可以搞定的工作&#xff0c;所以在開發過程當中需要&#xff1a; 1、 …

2019年4月第四周_2012年4月最佳怪胎文章

2019年4月第四周This past month we covered topics such as how to use a 64-bit web browser on Windows, the best tips and tweaks for getting the most out of Firefox, how to check out library books on your Kindle for free, and more. Join us as we look back at …

matlab循環遍歷數組_Matlab - 訪問for循環中最大值的索引,并使用它從數組中刪除值...

我想遞歸地找到一系列矩陣中的最大值(第8列&#xff0c;具體)&#xff0c;然后使用該最大值的索引來設置數組中的所有值&#xff0c;索引最大為NaN的最大索引(對于列14:16) . 很容易找到最大值和索引&#xff0c;但是使用for循環為多個數組做這件事我很難過 .如果沒有for循環&a…

【資料整理】編譯安裝nginx

【nginx】編譯安裝nginx 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311…

游蕩的奶牛

沙雕題目 讀錯題了&#xff0c;不想多說 轉載于:https://www.cnblogs.com/bullshit/p/9811058.html

物體成癮性_科技成癮使我們不那么快樂。 那是一個市場機會。

物體成癮性Compulsively checking social networks makes us less happy. I think we all understand this intuitively, the same way we understand that working out more and eating better is a good idea. 強迫檢查社交網絡使我們不那么開心。 我認為我們所有人都可以憑直…

mysql 不要統計null_淺談為什么Mysql數據庫盡量避免NULL

在Mysql中很多表都包含可為NULL(空值)的列&#xff0c;即使應用程序并不需要保存NULL也是如此&#xff0c;這是因為可為NULL是列的默認屬性。但我們常在一些Mysql性能優化的書或者一些博客中看到觀點&#xff1a;在數據列中&#xff0c;盡量不要用NULL 值&#xff0c;使用0&…

Swing學習1——總體概述

以下來自于JDK1.6 一、Swing學習我劃分為兩個方面&#xff1a; 一方面Swing的界面設計部分&#xff0c;包括相關組件類的繼承關系&#xff0c;組件的功能用途&#xff0c;布局管理&#xff1b; 1.首先繼承關系上自上而下為 java.lang.Object java.awt.Component java.awt.Conta…

裝飾設計模式和例題

文件復制程序&#xff1a; 將一個文件復制一份出來&#xff0c;實現方法很簡單&#xff0c;使用FileInputStream讀取文件內容&#xff0c;然后使用FileOutputStream寫入另一個文件&#xff0c;利用read方法的返回值作為while循環的條件&#xff0c;進行一邊讀一邊寫。 代碼示例…