搜尋
首頁php教程PHP开发SQL總結觸發器

SQL總結觸發器

Dec 14, 2016 pm 04:24 PM
sql觸發器

概念

觸發器是一種特殊類型的預存過程,不由使用者直接呼叫。建立觸發器時會對其進行定義,以便在對特定表或列作特定類型的資料修改時執行。

觸發器可以查詢其他資料表,而且可以包含複雜的 SQL 語句。 它們主要用於強制服從複雜的業務規則或要求。 例如,您可以根據客戶目前的帳戶狀態,控制是否允許插入新訂單。
觸發器也可用於強制引用完整性,以便在多個表中新增、更新或刪除資料列時,保留在這些表之間所定義的關係。

作用

1)觸發器可透過資料庫中的相關表實現級聯變更;透過級聯參考完整性限制可以更有效地執行這些變更。

2)觸發器可以強制比用 CHECK 約束定義的約束更為複雜的約束。與 CHECK 約束不同,觸發器可以引用其它表中的列。例如,觸發器可以使用另一個表中的 SELECT 來比較插入或更新的數據,以及執行其它操作,例如修改數據或顯示使用者定義錯誤訊息。

3)觸發器還可以強制執行業務規則

4)觸發器也可以評估資料修改前後的表狀態,並根據其差異採取對策。

實際應用

儘管觸發器有很多優點,但是在實際的專案開發中,特別是OOP思想的深入,觸發器的弊端也逐漸突顯,主要:

1、過多的觸發器使得資料邏輯變得複雜

2、資料操作比較隱含,不易進行調整修改

3、觸發器的功能逐漸在程式碼邏輯或事務中替代實現,更符合OO思想。

建議:

使用觸發器需慎重。

語法

CREATE TRIGGER trigger_name 
ON {table_name | view_name} 
{FOR | After | Instead of } [ insert, update,delete ]
AS           
    sql_statement

觸發器類型

SQL Server 包含兩種常規類型的觸發器:資料操作語言 (DML) 觸發器和資料定義語言 (DDL) 觸發器。 當INSERT、UPDATE 或 DELETE 語句修改指定表或檢視中的資料時,可使用 DML 觸發器。 DDL 觸發器激發預存程序以回應各種 DDL 語句,這些語句主要以CREATE、ALTER 和 DROP 開頭。 DDL 觸發器可用於管理任務,例如稽核和控制資料庫操作。

通常說的觸發器就是DML觸發器。

DML 觸發器在 INSERT、UPDATE 和 DELETE 語句上操作,並且有助於在表或視圖中修改資料時強制業務規則,擴展資料完整性。

在SQL Server2005後又增加了DDL觸發器。

DDL 觸發器將激發預存程序以回應事件。但與 DML 觸發器不同的是,它們不會為回應針對資料表或檢視的 UPDATE、INSERT 或 DELETE 語句而激發。相反,它們將為了響應各種資料定義語言 (DDL) 事件而激發。這些事件主要與以關鍵字 CREATE、ALTER 和 DROP 開頭的 Transact-SQL 語句對應。執行 DDL 式操作的系統預存程序也可以激發 DDL 觸發器。

DDL 觸發器使用場合:

要防止對資料庫架構進行某些變更。

希望資料庫中發生某種情況以回應資料庫架構中的變更。

要記錄資料庫架構中的變更或事件。

 

在這裡我們只講述DML觸發器。 DML觸發器又分以下分類:

1、 After觸發器

After觸發器要求只有執行某一操作insert、update、delete之後觸發器才會被觸發,且只能定義在表上。

     1)insert觸發器

     2)update觸發器

     3)delete ete

2、Instead of 觸發動作的觸發、執行器)而僅是執行觸發器本身。既可以在表上定義instead of觸發器,也可以在視圖上定義。

inserted與deleted對比

触发器有两个特殊的表:插入表(instered表)和删除表(deleted表)。这两张是逻辑表也是虚表。有系统在内存中创建者两张表,不会存储在数据库中。而且两张表的都是只读的,只能读取数据而不能修改数据。这两张表的结果总是与被改触发器应用的表的结构相同。当触发器完成工作后,这两张表就会被删除。Inserted表的数据是插入或是修改后的数据,而deleted表的数据是更新前的或是删除的数据。

SQL總結觸發器

具体应用

在触发器实际应用中,主要还是建立约束以及级联更新。在这里主要通过简单实例予以说明。

 1、触发器新增

原理:

 当触发INSERT触发器时,新的数据行就会被插入到触发器表和inserted表中。inserted表是一个逻辑表,它包含了已经插入的数据行的一个副本。inserted表包含了INSERT语句中已记录的插入动作。inserted表还允许引用由初始化INSERT语句而产生的日志数据。触发器通过检查inserted表来确定是否执行触发器动作或如何执行它。inserted表中的行总是触发器表中一行或多行的副本。

场景:增加学生信息时,要校验其年龄,暂定其年龄必须大于18,否则新增失败 

作用:校验约束

具体实例:

--触发器新增:只允许录取18岁以上学生
IF OBJECT_ID (N'TRIGER_Students_Insert', N'tr') IS NOT NULL
    DROP TRIGGER TRIGER_Students_Insert;
GO
CREATE TRIGGER TRIGER_Students_Insert
ON Students
FOR INSERT
AS
    declare @age int
    select @age=COUNT(Students.ID) FROM Students INNER JOIN inserted ON Students.ID =inserted.ID    
    PRINT @age
    if(@age<18)
    begin
        raiserror(&#39;学生年龄必须要大于18哦&#39;,16,8)
        rollback tran
    end

执行insert:

INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(105,'李四',16,'BeiJing',11)

执行结果:

会直接异常,返回错误信息

消息 50000,级别 16,状态 8,过程 TRIGER_Students_Insert,第 10 行
学生年龄必须要大于18哦
消息 3609,级别 16,状态 1,第 1 行
事务在触发器中结束。批处理已中止。

2、触发器更新

原理:

可将UPDATE语句看成两步操作:即捕获数据前像(before image)的DELETE语句,和捕获数据后像(after image)的INSERT语句。当在定义有触发器的表上执行UPDATE语句时,原始行(前像)被移入到deleted表,更新行(后像)被移入到inserted表。

触发器检查deleted表和inserted表以及被更新的表,来确定是否更新了多行以及如何执行触发器动作。

可以使用IF UPDATE语句定义一个监视指定列的数据更新的触发器。这样,就可以让触发器容易的隔离出特定列的活动。当它检测到指定列已经更新时,触发器就会进一步执行适当的动作,例如发出错误信息指出该列不能更新,或者根据新的更新的列值执行一系列的动作语句。

场景:

专业信息ID修改,对应的学生信息中专业ID也相应进行修改

实例实现:

--更新触发器:更新专业ID时,同时更新学生的专业信息
IF OBJECT_ID (N&#39;TRIGER_Majors_Update&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Majors_Update;
GO
CREATE TRIGGER TRIGER_Majors_Update
ON Majors
FOR UPDATE
AS
    IF UPDATE(ID)
    UPDATE Students Set MajorID=inserted.ID
    FROM Students,deleted,inserted
    WHERE Students.MajorID = deleted.ID

原始数据:

SQL總結觸發器

执行更新操作:

UPDATE Majors SET ID=12 WHERE ID=11

执行结果:

SQL總結觸發器

3、触发器删除

原理:

当触发DELETE触发器后,从受影响的表中删除的行将被放置到一个特殊的deleted表中。deleted表是一个逻辑表,它保留已被删除数据行的一个副本。deleted表还允许引用由初始化DELETE语句产生的日志数据。

使用DELETE触发器时,需要考虑以下的事项和原则:

当某行被添加到deleted表中时,它就不再存在于数据库表中;因此,deleted表和数据库表没有相同的行。

创建deleted表时,空间是从内存中分配的。deleted表总是被存储在高速缓存中。

为DELETE动作定义的触发器并不执行TRUNCATE TABLE语句,原因在于日志不记录TRUNCATE TABLE语句。

场景:学校某选修课取消。

处理逻辑:在删除课程的同时,需要删除该课程的选课信息。

触发器:

--删除触发器:删除课程时,同时删除该课程的选课信息
IF OBJECT_ID (N&#39;TRIGER_Courses_Delete&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Courses_Delete;
GO
CREATE TRIGGER TRIGER_Courses_Delete
ON Courses
FOR DELETE
AS
    DELETE SC
    FROM SC,deleted     
    WHERE SC.CourseID = deleted.ID

原始数据:

SQL總結觸發器

执行课程删除操作:

DELETE FROM Courses WHERE ID=10

执行结果:

可以看到,删除课程的同时,选修课程10的选课记录也被删除。

SQL總結觸發器

4、Instead Of 触发器

用Instead Of触发器实现与实例3相同的功能,具体实现代码如下:

--Instead Of触发器:删除课程时,同时删除该课程的选课信息
IF OBJECT_ID (N&#39;TRIGER_Courses_Instead_Delete&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Courses_Instead_Delete;
GO
CREATE TRIGGER TRIGER_Courses_Instead_Delete
ON Courses
Instead Of DELETE
AS
    declare @courseId int
    --获取要删除的课程ID
    SELECT @courseId=ID FROM deleted
    --删除选课信息
    DELETE FROM SC WHERE CourseID = @courseId
    --删除课程信息
    DELETE FROM Courses WHERE ID=@courseId

执行删除:

--测试用例DELETE FROM Courses WHERE ID=10

测试结果:

其测试结果与实例3相同。

本文测试用例脚本:

--数据准备
--学生信息表
IF OBJECT_ID (N'Students', N'U') IS NOT NULL
    DROP TABLE Students;
GO
CREATE TABLE Students(
    ID int primary key not null,
    Name nvarchar(50),
    Age int,
    City nvarchar(50),
    MajorID int
)


--专业信息表
IF OBJECT_ID (N'Majors', N'U') IS NOT NULL
    DROP TABLE Majors;
GO
CREATE TABLE Majors(
    ID int primary key not null,
    Name nvarchar(50)
)

--课程表
IF OBJECT_ID (N'Courses', N'U') IS NOT NULL
    DROP TABLE Courses;
GO
CREATE TABLE Courses(
    ID int primary key not null,
    Name nvarchar(50) not null
)

IF OBJECT_ID (N'SC', N'U') IS NOT NULL
    DROP TABLE SC;
GO
--选课表
CREATE TABLE SC(
    StudentID int not null,
    CourseID int not null,
    Score int    
)

/*
基础数据
*/

--专业信息
DELETE FROM Majors
INSERT INTO Majors(ID,Name) VALUES(10,'法律')
INSERT INTO Majors(ID,Name) VALUES(11,'美学')

--课程信息
DELETE FROM Courses
INSERT INTO Courses(ID,Name) VALUES (10,'太极拳')
INSERT INTO Courses(ID,Name) VALUES (11,'摄影入门')
INSERT INTO Courses(ID,Name) VALUES (12,'生命科学导论')

--学生信息
DELETE FROM Students
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(101,'Tom',20,'BeiJing',10)
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(103,'李明',20,'BeiJing',11)
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(104,'王涛',18,'ShangHai',11)


--选课信息
DELETE FROM SC
INSERT INTO SC(StudentID,CourseID) VALUES(101,10)
INSERT INTO SC(StudentID,CourseID) VALUES(101,11)
INSERT INTO SC(StudentID,CourseID) VALUES(102,12)



--触发器新增:只允许录取18岁以上学生
IF OBJECT_ID (N&#39;TRIGER_Students_Insert&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Students_Insert;
GO
CREATE TRIGGER TRIGER_Students_Insert
ON Students
FOR INSERT
AS
    declare @age int
    select @age=COUNT(Students.ID) FROM Students INNER JOIN inserted ON Students.ID =inserted.ID    
    PRINT @age
    if(@age<18)
    begin
        raiserror(&#39;学生年龄必须要大于18哦&#39;,16,8)
        rollback tran
    end

--测试用例
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(105,'李四',16,'BeiJing',11)
SELECT * FROM Students

--更新触发器:更新专业ID时,同时更新学生的专业信息
IF OBJECT_ID (N&#39;TRIGER_Majors_Update&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Majors_Update;
GO
CREATE TRIGGER TRIGER_Majors_Update
ON Majors
FOR UPDATE
AS
    IF UPDATE(ID)
    UPDATE Students Set MajorID=inserted.ID
    FROM Students,deleted,inserted
    WHERE Students.MajorID = deleted.ID

--测试用例
UPDATE Majors SET ID=12 WHERE ID=11

SELECT * FROM Students
SELECT * FROM Majors

--删除触发器:删除课程时,同时删除该课程的选课信息
IF OBJECT_ID (N&#39;TRIGER_Courses_Delete&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Courses_Delete;
GO
CREATE TRIGGER TRIGER_Courses_Delete
ON Courses
FOR DELETE
AS
    DELETE SC
    FROM SC,deleted     
    WHERE SC.CourseID = deleted.ID

--测试用例
DELETE FROM Courses WHERE ID=10

--执行结果
SELECT * FROM Students
SELECT * FROM Courses
SELECT * FROM SC



--Instead Of触发器:删除课程时,同时删除该课程的选课信息
IF OBJECT_ID (N&#39;TRIGER_Courses_Instead_Delete&#39;, N&#39;tr&#39;) IS NOT NULL
    DROP TRIGGER TRIGER_Courses_Instead_Delete;
GO
CREATE TRIGGER TRIGER_Courses_Instead_Delete
ON Courses
Instead Of DELETE
AS
    declare @courseId int
    --获取要删除的课程ID
    SELECT @courseId=ID FROM deleted
    --删除选课信息
    DELETE FROM SC WHERE CourseID = @courseId
    --删除课程信息
    DELETE FROM Courses WHERE ID=@courseId

--测试用例
DELETE FROM Courses WHERE ID=10

--执行结果
SELECT * FROM Students
SELECT * FROM Courses
SELECT * FROM SC


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。