SQL?Server觸發(fā)器常見應(yīng)用場(chǎng)景和注意事項(xiàng)詳解
一、什么是觸發(fā)器(Trigger)?
觸發(fā)器(Trigger)是一種特殊的存儲(chǔ)過程,它不會(huì)被人為調(diào)用,而是在對(duì)表執(zhí)行特定操作時(shí)自動(dòng)觸發(fā)執(zhí)行。
常見觸發(fā)條件包括:
INSERT(插入數(shù)據(jù))UPDATE(更新數(shù)據(jù))DELETE(刪除數(shù)據(jù))
可以理解為:
當(dāng)表發(fā)生變化時(shí),數(shù)據(jù)庫(kù)自動(dòng)執(zhí)行的一段“監(jiān)聽程序”。
觸發(fā)器的典型用途
數(shù)據(jù)審計(jì)(記錄誰(shuí)改了什么數(shù)據(jù))
數(shù)據(jù)校驗(yàn)(防止非法操作)
自動(dòng)維護(hù)關(guān)聯(lián)數(shù)據(jù)
業(yè)務(wù)規(guī)則約束(如庫(kù)存不能為負(fù))
二、觸發(fā)器的分類
SQL Server 中主要有兩類觸發(fā)器:
1. DML 觸發(fā)器(針對(duì)表)
作用對(duì)象:INSERT / UPDATE / DELETE
分為兩種:
(1)AFTER 觸發(fā)器(之后觸發(fā))
在操作完成后執(zhí)行。
CREATE TRIGGER trg_AfterInsert
ON Student
AFTER INSERT
AS
BEGIN
PRINT '插入數(shù)據(jù)成功'
END(2)INSTEAD OF 觸發(fā)器(替代執(zhí)行)
替代原本的操作執(zhí)行,常用于視圖或復(fù)雜邏輯控制。
CREATE TRIGGER trg_InsteadDelete
ON Student
INSTEAD OF DELETE
AS
BEGIN
PRINT '禁止刪除學(xué)生記錄'
END2. DDL 觸發(fā)器(針對(duì)數(shù)據(jù)庫(kù)級(jí)操作)
用于監(jiān)聽:
CREATE TABLE
DROP TABLE
ALTER TABLE
CREATE LOGIN 等
CREATE TRIGGER trg_DDL
ON DATABASE
FOR DROP_TABLE
AS
BEGIN
PRINT '禁止刪除表結(jié)構(gòu)'
END三、Inserted 與 Deleted 表(核心概念)
在 DML 觸發(fā)器中,SQL Server 提供了兩個(gè)虛擬表:
| 操作 | Inserted 表 | Deleted 表 |
|---|---|---|
| INSERT | 新數(shù)據(jù) | 空 |
| DELETE | 空 | 原數(shù)據(jù) |
| UPDATE | 新數(shù)據(jù) | 舊數(shù)據(jù) |
示例:記錄學(xué)生表修改日志
CREATE TRIGGER trg_UpdateLog
ON Student
AFTER UPDATE
AS
BEGIN
INSERT INTO StudentLog(StudentID, OldName, NewName, UpdateTime)
SELECT d.ID, d.Name, i.Name, GETDATE()
FROM deleted d
JOIN inserted i ON d.ID = i.ID
END四、觸發(fā)器的常見應(yīng)用場(chǎng)景
1. 數(shù)據(jù)審計(jì)(日志記錄)
CREATE TRIGGER trg_InsertLog
ON Orders
AFTER INSERT
AS
BEGIN
INSERT INTO OrderLog(OrderID, CreateTime)
SELECT ID, GETDATE() FROM inserted
END2. 數(shù)據(jù)校驗(yàn)(防止非法數(shù)據(jù))
例如:禁止工資為負(fù)數(shù)
CREATE TRIGGER trg_CheckSalary
ON Employee
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT 1 FROM inserted WHERE Salary < 0)
BEGIN
ROLLBACK
RAISERROR('工資不能為負(fù)數(shù)',16,1)
END
END3. 維護(hù)關(guān)聯(lián)數(shù)據(jù)(如庫(kù)存)
當(dāng)訂單插入時(shí),自動(dòng)減少庫(kù)存。
五、觸發(fā)器的注意事項(xiàng)(非常重要)
1. 觸發(fā)器是“針對(duì)集合”的,不是單行
錯(cuò)誤寫法(假設(shè)只有一行):
SELECT @id = ID FROM inserted
正確思維:要按多行數(shù)據(jù)處理。
2. 不要在觸發(fā)器中寫復(fù)雜業(yè)務(wù)邏輯
原因:
難調(diào)試
性能差
容易造成死鎖
影響主業(yè)務(wù)SQL執(zhí)行
觸發(fā)器適合做:
? 校驗(yàn)
? 日志
? 簡(jiǎn)單數(shù)據(jù)同步
不適合:
? 復(fù)雜計(jì)算
? 調(diào)用外部接口
? 長(zhǎng)事務(wù)邏輯
3. 謹(jǐn)慎使用 ROLLBACK
觸發(fā)器中一旦 ROLLBACK,原 SQL 操作也會(huì)失敗。
4. 注意遞歸觸發(fā)
如果觸發(fā)器中再次修改本表,可能導(dǎo)致無(wú)限循環(huán)。
可關(guān)閉遞歸:
ALTER DATABASE dbname SET RECURSIVE_TRIGGERS OFF
六、觸發(fā)器與存儲(chǔ)過程的區(qū)別
| 對(duì)比項(xiàng) | 觸發(fā)器 | 存儲(chǔ)過程 |
|---|---|---|
| 是否自動(dòng)執(zhí)行 | 是 | 否 |
| 是否可傳參 | 否 | 是 |
| 調(diào)用方式 | 系統(tǒng)觸發(fā) | 手動(dòng)調(diào)用 |
| 使用場(chǎng)景 | 監(jiān)聽數(shù)據(jù)變化 | 業(yè)務(wù)邏輯處理 |
七、最佳實(shí)踐總結(jié)
推薦使用場(chǎng)景:
數(shù)據(jù)審計(jì)日志
簡(jiǎn)單校驗(yàn)規(guī)則
防誤操作保護(hù)
數(shù)據(jù)同步
不推薦使用場(chǎng)景:
核心業(yè)務(wù)邏輯
高并發(fā)復(fù)雜處理
跨系統(tǒng)調(diào)用
一句話原則:
觸發(fā)器 = 數(shù)據(jù)層的“守門員”,不是業(yè)務(wù)層的“指揮官”。
八、結(jié)語(yǔ)
SQL Server 觸發(fā)器是一把“雙刃劍”:
用得好:提高數(shù)據(jù)安全性與一致性
用不好:降低性能、增加維護(hù)成本
建議遵循:
少用、慎用、簡(jiǎn)單用。
把復(fù)雜業(yè)務(wù)邏輯放在:
存儲(chǔ)過程
服務(wù)層(Java / C#)
應(yīng)用程序中處理
面試回答話術(shù)(簡(jiǎn)潔版)
“觸發(fā)器主要用于實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)完整性、審計(jì)日志、自動(dòng)更新冗余統(tǒng)計(jì)字段以及軟刪除。但我清楚它的代價(jià):隱式執(zhí)行、難以調(diào)試、容易引發(fā)性能問題和死鎖。
使用時(shí)我會(huì)特別注意:
基于集合處理 inserted/deleted,絕不用游標(biāo)或逐行操作;
避免在觸發(fā)器內(nèi)進(jìn)行耗時(shí)操作或開啟新事務(wù);
關(guān)閉遞歸觸發(fā)器(除非有明確需求);
對(duì)批量操作做充分測(cè)試;
優(yōu)先考慮用約束、計(jì)算列或應(yīng)用層邏輯替代觸發(fā)器。
總的來說,觸發(fā)器是最后的手段,能不用就不用;但遇到必須保證數(shù)據(jù)強(qiáng)一致性且無(wú)法用其他方法實(shí)現(xiàn)時(shí),它是個(gè)有效的工具。”
總結(jié)
到此這篇關(guān)于SQL Server觸發(fā)器常見應(yīng)用場(chǎng)景和注意事項(xiàng)詳解的文章就介紹到這了,更多相關(guān)SQL Server觸發(fā)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Sql Server中Substring函數(shù)的用法實(shí)例解析
在sqlserver中substring函數(shù)是用來處理字符串的,常用于字符串截取了,下面我來給大家介紹下Sql Server中Substring函數(shù)的用法實(shí)例解析,需要的朋友參考下吧2016-12-12
t-sql/mssql用命令行導(dǎo)入數(shù)據(jù)腳本的SQL語(yǔ)句示例
這篇文章主要介紹了t-sql或mssql用命令行導(dǎo)入數(shù)據(jù)腳本的SQL語(yǔ)句示例,大家參考使用吧2013-11-11
解決Navicat連接本地sqlserver數(shù)據(jù)庫(kù)成功后沒有庫(kù)表數(shù)據(jù)的問題
本文主要給大家介紹了如何解決Navicat連接本地sqlserver數(shù)據(jù)庫(kù)成功后沒有庫(kù)表數(shù)據(jù)的問題,文中有詳細(xì)的原因分析和解決方法,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10
SQL Server 數(shù)據(jù)庫(kù)分區(qū)分表(水平分表)詳細(xì)步驟
最近幾個(gè)擔(dān)心網(wǎng)站數(shù)據(jù)量大會(huì)影響sqlserver數(shù)據(jù)庫(kù)的性能,所以提前將數(shù)據(jù)庫(kù)分表處理好,下面是ExceptionalBoy同學(xué)分享的詳細(xì)方法,需要的朋友可以參考下2021-03-03
解決無(wú)法在unicode和非unicode字符串?dāng)?shù)據(jù)類型之間轉(zhuǎn)換的方法詳解
本篇文章是對(duì)無(wú)法在unicode和非unicode字符串?dāng)?shù)據(jù)類型之間轉(zhuǎn)換的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
動(dòng)態(tài)SQL中返回?cái)?shù)值的實(shí)現(xiàn)代碼
最近在做一個(gè)paypal抓取數(shù)據(jù)的程序,由于所有字段和paypal之間存在對(duì)應(yīng)映射的關(guān)系,所以所有的sql語(yǔ)句必須得拼接傳到存儲(chǔ)過程里去執(zhí)行2011-12-12
淺析SQL Server的嵌套存儲(chǔ)過程中使用同名的臨時(shí)表怪像
這篇文章主要介紹了淺析SQL Server的嵌套存儲(chǔ)過程中使用同名的臨時(shí)表怪像,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02

