程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> MSSQL >> sqlserver 觸發器實例代碼

sqlserver 觸發器實例代碼

編輯:MSSQL

sqlserver 觸發器實例代碼。本站提示廣大學習愛好者:(sqlserver 觸發器實例代碼)文章只能為提供參考,不一定能成為您想要的結果。以下是sqlserver 觸發器實例代碼正文


界說: 作甚觸發器?在SQL Server外面也就是對某一個表的必定的操作,觸發某種前提,從而履行的一段法式。觸發器是一個特別的存儲進程。
罕見的觸發器有三種:分離運用於Insert , Update , Delete 事宜。
我為何要應用觸發器?好比,這麼兩個表:

Create Table Student( --先生表
StudentID int primary key, --學號
....
)
Create Table BorrowRecord( --先生借書記載表
BorrowRecord int identity(1,1), --流水號
StudentID int , --學號
BorrowDate datetime, --借出時光
ReturnDAte Datetime, --清償時光
...
)

用到的功效有:
1.假如我更改了先生的學號,我願望他的借書記載依然與這個先生相干(也就是同時更改借書記載表的學號);
2.假如該先生曾經卒業,我願望刪除他的學號的同時,也刪除它的借書記載。
等等。
這時候候可以用到觸發器。關於1,創立一個Update觸發器:

Create Trigger truStudent
On Student --在Student表中創立觸發器
for Update --為何事宜觸發
As --事宜觸發後所要做的工作
if Update(StudentID)
begin
Update BorrowRecord
Set StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i --Deleted和Inserted暫時表
Where br.StudentID=d.StudentID
end

懂得觸發器外面的兩個暫時的表:Deleted , Inserted 。留意Deleted 與Inserted分離表現觸發事宜的表“舊的一筆記錄”和“新的一筆記錄”。
一個數據庫體系中有兩個虛擬表用於存儲在表中記載修改的信息,分離是:
虛擬表Inserted 虛擬表Deleted
在表記載新增時 寄存新增的記載 不存儲記載
修正時 寄存用來更新的新記載 寄存更新前的記載
刪除時 不存儲記載 寄存被刪除的記載
一個Update 的進程可以看做為:生成新的記載到Inserted表,復制舊的記載到Deleted表,然後刪除Student記載並寫入新記載。
關於2,創立一個Delete觸發器

Create trigger trdStudent
On Student
for Delete
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID

從這兩個例子我們可以看到了觸發器的症結:A.2個暫時的表;B.觸發機制。
SQL觸發器實例2

/*
樹立虛擬測試情況,包括:表[卷煙庫存表],表[卷煙發賣表]。
請年夜家留意跟蹤這兩個表的數據,領會觸發器究竟履行了甚麼營業邏輯,對數據有甚麼影響。
為了能更清楚的表述觸發器的感化,表構造存在數據冗余,且不相符第三范式,這裡特此解釋。
*/
USE Master
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷煙庫存表')
DROP TABLE 卷煙庫存表
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷煙發賣表')
DROP TABLE 卷煙發賣表
GO
--營業規矩:發賣金額 = 發賣數目 * 發賣單價 營業規矩。
CREATE TABLE 卷煙發賣表
(
卷煙品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
購貨商 VARCHAR(40) NULL,
發賣數目 INT NULL,
發賣單價 MONEY NULL,
發賣金額 MONEY NULL
)
GO
--營業規矩:庫存金額 = 庫存數目 * 庫存單價 營業規矩。
CREATE TABLE 卷煙庫存表
(
卷煙品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
庫存數目 INT NULL,
庫存單價 MONEY NULL,
庫存金額 MONEY NULL
)
GO
--創立觸發器,示例1
/*
創立觸發器[T_INSERT_卷煙庫存表],這個觸發器較簡略。
解釋: 每當[卷煙庫存表]產生 INSERT 舉措,則激發該觸發器。
觸發器功效: 強迫履行營業規矩,包管拔出的數據中,庫存金額 = 庫存數目 * 庫存單價。
留意: [INSERTED]、[DELETED]為體系表,弗成創立、修正、刪除,但可以挪用。
主要: 這兩個體系表的構造同拔出數據的表的構造。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷煙庫存表')
DROP TRIGGER T_INSERT_卷煙庫存表
GO
CREATE TRIGGER T_INSERT_卷煙庫存表
ON 卷煙庫存表
FOR INSERT
AS
--提交事務處置
BEGIN TRANSACTION
--強迫履行以下語句,包管營業規矩
UPDATE 卷煙庫存表
SET 庫存金額 = 庫存數目 * 庫存單價
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 from INSERTED)
COMMIT TRANSACTION
GO
/*
針對[卷煙庫存表],拔出測試數據:
留意,第一條數據(紅塔山新權勢)中的數據相符營業規矩,
第二條數據(紅塔隱士為峰)中,[庫存金額]空,不相符營業規矩,
第三條數據(雲南映像)中,[庫存金額]不等於[庫存數目]乘以[庫存單價],不相符營業規矩。
第四條數據庫存數目為0。
請留意在拔出數據後,檢討[卷煙庫存表]中的數據能否 庫存金額 = 庫存數目 * 庫存單價。
*/
INSERT INTO 卷煙庫存表(卷煙品牌,庫存數目,庫存單價,庫存金額)
SELECT '紅塔山新權勢',100,12,1200 UNION ALL
SELECT '紅塔隱士為峰',100,22,NULL UNION ALL
SELECT '雲南映像',100,60,500 UNION ALL
SELECT '玉溪',0,30,0
GO
--查詢數據
SELECT * FROM 卷煙庫存表
GO
/*

成果集
RecordId 卷煙品牌 庫存數目 庫存單價 庫存金額
-------- ------------ -------- ------- ---------
1 紅塔山新權勢 100 12.0000 1200.0000
2 紅塔隱士為峰 100 22.0000 2200.0000
3 雲南映像 100 60.0000 6000.0000
4 玉溪 0 30.0000 .0000
(所影響的行數為 4 行)
*/
--觸發器示例2

/*
創立觸發器[T_INSERT_卷煙發賣表],該觸發器較龐雜。
解釋: 每當[卷煙庫存表]產生 INSERT 舉措,則激發該觸發器。
觸發器功效: 完成營業規矩。
營業規矩: 假如發賣的卷煙品牌不存在庫存或許庫存為零,則前往毛病。
不然則主動削減[卷煙庫存表]中對應品牌卷煙的庫存數目和庫存金額。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷煙發賣表')
DROP TRIGGER T_INSERT_卷煙發賣表
GO
CREATE TRIGGER T_INSERT_卷煙發賣表
ON 卷煙發賣表
FOR INSERT
AS
BEGIN TRANSACTION
--檢討數據的正當性:發賣的卷煙能否有庫存,或許庫存能否年夜於零
IF NOT EXISTS (
SELECT 庫存數目
FROM 卷煙庫存表
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED)
)
BEGIN
--前往毛病提醒
RAISERROR('毛病!該卷煙不存在庫存,不克不及發賣。',16,1)
--回滾事務
ROLLBACK
RETURN
END
IF EXISTS (
SELECT 庫存數目
FROM 卷煙庫存表
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED) AND
庫存數目 <= 0
)
BEGIN
--前往毛病提醒
RAISERROR('毛病!該卷煙庫存小於等於0,不克不及發賣。',16,1)
--回滾事務
ROLLBACK
RETURN
END
--對正當的數據停止處置
--強迫履行以下語句,包管營業規矩
UPDATE 卷煙發賣表
SET 發賣金額 = 發賣數目 * 發賣單價
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED)
DECLARE @卷煙品牌 VARCHAR(40)
SET @卷煙品牌 = (SELECT 卷煙品牌 FROM INSERTED)
DECLARE @發賣數目 MONEY
SET @發賣數目 = (SELECT 發賣數目 FROM INSERTED)
UPDATE 卷煙庫存表
SET 庫存數目 = 庫存數目 - @發賣數目,
庫存金額 = (庫存數目 - @發賣數目)*庫存單價
WHERE 卷煙品牌 = @卷煙品牌
COMMIT TRANSACTION
GO
--請年夜家自行跟蹤[卷煙庫存表]和[卷煙發賣表]的數據變更。
--針對[卷煙發賣表],拔出第一條測試數據,該數據是正常的。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅塔山新權勢','某購貨商',10,12,1200
GO
--針對[卷煙發賣表],拔出第二條測試數據,該數據 發賣金額 不等於 發賣單價 * 發賣數目。
--觸發器將主動更負數據,使 發賣金額 等於 發賣單價 * 發賣數目。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅塔隱士為峰','某購貨商',10,22,2000
GO
--針對[卷煙發賣表],拔出第三條測試數據,該數據中的卷煙品牌在 卷煙庫存表中找不到對應。
--觸發器將報錯。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅河V8','某購貨商',10,60,600
GO

/*
成果集
辦事器: 新聞 50000,級別 16,狀況 1,進程 T_INSERT_卷煙發賣表,行 15
毛病!該卷煙不存在庫存,不克不及發賣。
*/
--針對[卷煙發賣表],拔出第三條測試數據,該數據中的卷煙品牌在 卷煙庫存表中庫存為0。
--觸發器將報錯。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '玉溪','某購貨商',10,30,300
GO
/*
成果集
辦事器: 新聞 50000,級別 16,狀況 1,進程 T_INSERT_卷煙發賣表,行 29
毛病!該卷煙庫存小於等於0,不克不及發賣。
*/
--查詢數據
SELECT * FROM 卷煙庫存表
SELECT * FROM 卷煙發賣表
GO
/*
彌補:
1、本示例重要經由過程一個簡略的營業規矩完成來停止觸發器應用的解釋,詳細的要依據須要靈巧處置;
2、關於觸發器要懂得並應用好 INSERTED ,DELETED 兩個體系表;
3、本示例創立的觸發器都是 FOR INSERT ,詳細的語法可參考:
Trigger語法

CREATE TRIGGER trigger_name
ON { table | view }
[ WITH ENCRYPTION ] --用於加密觸發器
{
{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
[ { IF UPDATE ( column )
[ { AND | OR } UPDATE ( column ) ]
[ ...n ]
| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )
{ comparison_operator } column_bitmask [ ...n ]
} ]
sql_statement [ ...n ]
}
}

4、關於觸發器,還應當留意
(1)、DELETE 觸發器不克不及捕捉 TRUNCATE TABLE 語句。
(2)、觸發器中不許可以下 Transact-SQL 語句:
ALTER DATABASE CREATE DATABASE DISK INIT
DISK RESIZE DROP DATABASE LOAD DATABASE
LOAD LOG RECONFIGURE RESTORE DATABASE
RESTORE LOG
(3)、觸發器最多可以嵌套 32 層。
*/
--修正觸發器
--本質上,是將 CREATE TRIGGER ... 修正為 ALTER TRIGGER ...便可。
--刪除觸發器
DROP TRIGGER xxx
GO
--刪除測試情況
DROP TABLE 卷煙庫存表
GO
DROP TABLE 卷煙發賣表
GO
DROP TRIGGER T_INSERT_卷煙庫存表
GO
DROP TRIGGER T_INSERT_卷煙發賣表
GO
##################################################################
觸發器的基本常識和例子
:create trigger tr_name
on table/view
{for | after | instead of } [update][,][insert][,][delete]
[with encryption]
as {batch | if update (col_name) [{and|or} update (col_name)] }
解釋:
1 tr_name :觸發器稱號
2 on table/view :觸發器所感化的表。一個觸發器只能感化於一個表
3 for 和after :同義
4 after 與instead of :sql 2000新增項目afrer 與 instead of 的差別
After
在觸發事宜產生今後才被激活,只可以樹立在表上
Instead of
取代了響應的觸發事宜而被履行,既可以樹立在表上也能夠樹立在視圖上
5 insert、update、delete:激活觸發器的三種操作,可以同時履行,也可選其一
6 if update (col_name):注解所作的操尴尬刁難指定列能否有影響,有影響,則激活觸發器。另外,由於delete 操作只對行有影響,
所以假如應用delete操作就不克不及用這條語句了(固然應用也不失足,然則不克不及激活觸發器,沒意義)。
7 觸發器履行時用到的兩個特別表:deleted ,inserted
deleted 和inserted 可以說是一種特別的暫時表,是在停止激活觸發器時由體系主動生成的,其構造與觸發器感化的表構造是一
樣的,只是寄存 的數據有差別。

上面表格解釋deleted 與inserted 數據的差別
deleted 與inserted 數據的差別
Inserted
寄存停止insert和update 操作後的數據
Deleted
寄存停止delete 和update操作前的數據
留意:update 操作相當於先輩行delete 再停止insert ,所以在停止update操作時,修正前的數據拷貝一條到deleted 表中,修正後
的數據在存到觸發器感化的表的同時,也同時生成一條拷貝到insered表中

SQL Server 2000中的觸發器應用

觸發器是數據庫運用中的重用對象,它的運用很普遍。這幾天寫一個化學數據統計方面的軟件,須要依據采樣,主動盤算方差,在這裡,我應用了觸發器。
  上面我摘錄了SQL Server官方教程中的一段關於觸發器的文字,確切有效的一點文字描寫。
  可以界說一個不管什麼時候用INSERT語句向表中拔出數據時都邑履行的觸發器。
  當觸發INSERT觸發器時,新的數據行就會被拔出到觸發器表和inserted表中。inserted表是一個邏輯表,它包括了曾經拔出的數據行的一個正本。inserted表包括了INSERT語句中已記載的拔出舉措。inserted表還許可援用由初始化INSERT語句而發生的日記數據。觸發器經由過程檢討inserted表來肯定能否履行觸發器舉措或若何履行它。inserted表中的行老是觸發器表中一行或多行的正本。
  日記記載了一切修正數據的舉措(INSERT、UPDATE和DELETE語句),但在事務日記中的信息是弗成讀的。但是,inserted表許可你援用由INSERT語句惹起的日記變更,如許便可以將拔出數據與產生的變更停止比擬,來驗證它們或采用進一步的舉措。也能夠直接援用拔出的數據,而不用將它們存儲到變量中。
  示例
  在本例中,將創立一個觸發器。不管什麼時候訂購產物(不管什麼時候向Order Details表中拔出一筆記錄),這個觸發器都將更新Products表中的一列(UnitsInStock)。用本來的值減去訂購的數目值即為新值。



USE Northwind

CREATE TRIGGER OrdDet_Insert
ON [Order Details]
FOR INSERT
AS
UPDATE P SET
UnitsInStock = P.UnitsInStock – I.Quantity
FROM Products AS P INNER JOIN Inserted AS I
ON P.ProductID = I.ProductID


  DELETE觸發器的任務進程
  當觸發DELETE觸發器後,從受影響的表中刪除的即將被放置到一個特別的deleted表中。deleted表是一個邏輯表,它保存已被刪除數據行的一個正本。deleted表還許可援用由初始化DELETE語句發生的日記數據。
  應用DELETE觸發器時,須要斟酌以下的事項和准繩:
  ·當某行被添加到deleted表中時,它就不再存在於數據庫表中;是以,deleted表和數據庫表沒有雷同的行。
  ·創立deleted表時,空間是從內存平分配的。deleted表老是被存儲在高速緩存中。
  ·為DELETE舉措界說的觸發器其實不履行TRUNCATE TABLE語句,緣由在於日記不記載TRUNCATE TABLE語句。
  示例
  在本例中,將創立一個觸發器,不管什麼時候刪除一個產物種別(即從Categories表中刪除一筆記錄),該觸發器都邑更新Products表中的Discontinued列。一切受影響的產物都標志為1,標示不再應用這些產物了。


USE Northwind

CREATE TRIGGER Category_Delete
ON Categories
FOR DELETE
AS
UPDATE P SET Discontinued = 1
FROM Products AS P INNER JOIN deleted AS d
ON P.CategoryID = d.CategoryID


  UPDATE觸發器的任務進程
  可將UPDATE語句算作兩步操作:即捕捉數據前像(before image)的DELETE語句,和捕捉數據後像(after image)的INSERT語句。當在界說有觸發器的表上履行UPDATE語句時,原始行(前像)被移入到deleted表,更新行(後像)被移入到inserted表。
  觸發器檢討deleted表和inserted表和被更新的表,來肯定能否更新了多行和若何履行觸發器舉措。
  可使用IF UPDATE語句界說一個監督指定列的數據更新的觸發器。如許,便可以讓觸發器輕易的隔離出特定列的運動。當它檢測到指定列曾經更新時,觸發器就會進一步履行恰當的舉措,例如收回毛病信息指出該列不克不及更新,或許依據新的更新的列值履行一系列的舉措語句。
  語法



IF UPDATE (<column_name>)

  例1
  本例阻攔用戶修正Employees表中的EmployeeID列。



USE Northwind

GO
CREATE TRIGGER Employee_Update
ON Employees
FOR UPDATE
AS
IF UPDATE (EmployeeID)
BEGIN
RAISERROR ('Transaction cannot be processed.\
***** Employee ID number cannot be modified.', 10, 1)
ROLLBACK TRANSACTION
END



  INSTEAD OF觸發器的任務進程
  可以在表或視圖上指定INSTEAD OF觸發器。履行這類觸發器就可以夠替換原始的觸動員作。INSTEAD OF觸發器擴大了視圖更新的類型。關於每種觸動員作(INSERT、UPDATE或 DELETE),每個表或視圖只能有一個INSTEAD OF觸發器。
  INSTEAD OF觸發器被用於更新那些沒有方法經由過程正常方法更新的視圖。例如,平日不克不及在一個基於銜接的視圖長進行DELETE操作。但是,可以編寫一個INSTEAD OF DELETE觸發器來完成刪除。上述觸發器可以拜訪那些假如視圖是一個真實的表時曾經被刪除的數據行。將被刪除的行存儲在一個名為deleted的任務表中,就像AFTER觸發器一樣。類似地,在UPDATE INSTEAD OF觸發器或許INSERT INSTEAD OF觸發器中,你可以拜訪inserted表中的新行。
  不克不及在帶有WITH CHECK OPTION界說的視圖中創立INSTEAD OF觸發器。
示例
  在本例中,創立了一個德國客戶表和一個墨西哥客戶表。放置在視圖上的INSTEAD OF觸發器將把更新操作從新定向到恰當的基表上。這時候產生的拔出是對CustomersGer表的拔出而不是對視圖的拔出。
  創立兩個包括客戶數據的表:



SELECT * INTO CustomersGer FROM Customers WHERE Customers.Country = 'Germany'

SELECT * INTO CustomersMex FROM Customers WHERE Customers.Country = 'Mexico'
GO


  在該數據上創立視圖:


CREATE VIEW CustomersView AS

SELECT * FROM CustomersGer
UNION
SELECT * FROM CustomersMex
GO


  創立一個在上述視圖上的INSTEAD OF觸發器:


CREATE TRIGGER Customers_Update2

ON CustomersView
INSTEAD OF UPDATE AS
DECLARE @Country nvarchar(15)
SET @Country = (SELECT Country FROM Inserted)
IF @Country = 'Germany'
BEGIN
UPDATE CustomersGer
SET CustomersGer.Phone = Inserted.Phone
FROM CustomersGer JOIN Inserted
ON CustomersGer.CustomerID = Inserted.CustomerID
END
ELSE
IF @Country = 'Mexico'
BEGIN
UPDATE CustomersMex
SET CustomersMex.Phone = Inserted.Phone
FROM CustomersMex JOIN Inserted
ON CustomersMex.CustomerID = Inserted.CustomerID
END


  經由過程更新視圖,測試觸發器:


UPDATE CustomersView SET Phone = ' 030-007xxxx'

WHERE CustomerID = 'ALFKI'
SELECT CustomerID, Phone FROM CustomersView
WHERE CustomerID = 'ALFKI'
SELECT CustomerID, Phone FROM CustomersGer
WHERE CustomerID = 'ALFKI'


  那末詳細的講,關於多列數據,若何盤算方差呢?:



CREATE TRIGGER [calT1T2T3] ON dbo.DCLB

FOR INSERT,UPDATE
AS
update P
SET
/**//*
盤算方差的觸發器
*/
P.T1=(I.P1+I.P2+I.P3+I.P4+I.P5+I.P6),
P.T2=(I.Y1+I.Y2+I.Y3+I.Y4+I.Y5+I.Y6 ),
P.T3=SQRT(P.T1*P.T1+P.T2*P.T2)
FROM DCLB AS P INNER JOIN Inserted AS I
ON P.SID = I.SID


  觸發器的應用很便利,並且也很簡略,主要的是懂得inserted進程。可將UPDATE語句算作兩步操作:即捕捉數據前像(before image)的DELETE語句,和捕捉數據後像(after image)的INSERT語句。當在界說有觸發器的表上履行UPDATE語句時,原始行(前像)被移入到deleted表,更新行(後像)被移入到inserted表。觸發器檢討deleted表和inserted表和被更新的表,來肯定能否更新了多行和若何履行觸發器舉措。


熟悉了一下觸發器的感化!

/*
樹立虛擬測試情況,包括:表[卷煙庫存表],表[卷煙發賣表]。
請年夜家留意跟蹤這兩個表的數據,領會觸發器究竟履行了甚麼營業邏輯,對數據有甚麼影響。
為了能更清楚的表述觸發器的感化,表構造存在數據冗余,且不相符第三范式,這裡特此解釋。
*/
USE Master
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷煙庫存表')
DROP TABLE 卷煙庫存表
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷煙發賣表')
DROP TABLE 卷煙發賣表
GO
--營業規矩:發賣金額 = 發賣數目 * 發賣單價 營業規矩。
CREATE TABLE 卷煙發賣表
(
卷煙品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
購貨商 VARCHAR(40) NULL,
發賣數目 INT NULL,
發賣單價 MONEY NULL,
發賣金額 MONEY NULL
)
GO
--營業規矩:庫存金額 = 庫存數目 * 庫存單價 營業規矩。
CREATE TABLE 卷煙庫存表
(
卷煙品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
庫存數目 INT NULL,
庫存單價 MONEY NULL,
庫存金額 MONEY NULL
)
GO
--創立觸發器,示例1
/*
創立觸發器[T_INSERT_卷煙庫存表],這個觸發器較簡略。
解釋: 每當[卷煙庫存表]產生 INSERT 舉措,則激發該觸發器。
觸發器功效: 強迫履行營業規矩,包管拔出的數據中,庫存金額 = 庫存數目 * 庫存單價。
留意: [INSERTED]、[DELETED]為體系表,弗成創立、修正、刪除,但可以挪用。
主要: 這兩個體系表的構造同拔出數據的表的構造。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷煙庫存表')
DROP TRIGGER T_INSERT_卷煙庫存表
GO
CREATE TRIGGER T_INSERT_卷煙庫存表
ON 卷煙庫存表
FOR INSERT
AS
--提交事務處置
BEGIN TRANSACTION
--強迫履行以下語句,包管營業規矩
UPDATE 卷煙庫存表
SET 庫存金額 = 庫存數目 * 庫存單價
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 from INSERTED)
COMMIT TRANSACTION
GO
/*
針對[卷煙庫存表],拔出測試數據:
留意,第一條數據(紅塔山新權勢)中的數據相符營業規矩,
第二條數據(紅塔隱士為峰)中,[庫存金額]空,不相符營業規矩,
第三條數據(雲南映像)中,[庫存金額]不等於[庫存數目]乘以[庫存單價],不相符營業規矩。
第四條數據庫存數目為0。
請留意在拔出數據後,檢討[卷煙庫存表]中的數據能否 庫存金額 = 庫存數目 * 庫存單價。
*/
INSERT INTO 卷煙庫存表(卷煙品牌,庫存數目,庫存單價,庫存金額)
SELECT '紅塔山新權勢',100,12,1200 UNION ALL
SELECT '紅塔隱士為峰',100,22,NULL UNION ALL
SELECT '雲南映像',100,60,500 UNION ALL
SELECT '玉溪',0,30,0
GO
--查詢數據
SELECT * FROM 卷煙庫存表
GO

/*
成果集
RecordId 卷煙品牌 庫存數目 庫存單價 庫存金額
-------- ------------ -------- ------- ---------
1 紅塔山新權勢 100 12.0000 1200.0000
2 紅塔隱士為峰 100 22.0000 2200.0000
3 雲南映像 100 60.0000 6000.0000
4 玉溪 0 30.0000 .0000
(所影響的行數為 4 行)
*/
--觸發器示例2

/*
創立觸發器[T_INSERT_卷煙發賣表],該觸發器較龐雜。
解釋: 每當[卷煙庫存表]產生 INSERT 舉措,則激發該觸發器。
觸發器功效: 完成營業規矩。
營業規矩: 假如發賣的卷煙品牌不存在庫存或許庫存為零,則前往毛病。
不然則主動削減[卷煙庫存表]中對應品牌卷煙的庫存數目和庫存金額。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷煙發賣表')
DROP TRIGGER T_INSERT_卷煙發賣表
GO
CREATE TRIGGER T_INSERT_卷煙發賣表
ON 卷煙發賣表
FOR INSERT
AS
BEGIN TRANSACTION
--檢討數據的正當性:發賣的卷煙能否有庫存,或許庫存能否年夜於零
IF NOT EXISTS (
SELECT 庫存數目
FROM 卷煙庫存表
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED)
)
BEGIN
--前往毛病提醒
RAISERROR('毛病!該卷煙不存在庫存,不克不及發賣。',16,1)
--回滾事務
ROLLBACK
RETURN
END
IF EXISTS (
SELECT 庫存數目
FROM 卷煙庫存表
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED) AND
庫存數目 <= 0
)
BEGIN
--前往毛病提醒
RAISERROR('毛病!該卷煙庫存小於等於0,不克不及發賣。',16,1)
--回滾事務
ROLLBACK
RETURN
END
--對正當的數據停止處置
--強迫履行以下語句,包管營業規矩
UPDATE 卷煙發賣表
SET 發賣金額 = 發賣數目 * 發賣單價
WHERE 卷煙品牌 IN (SELECT 卷煙品牌 FROM INSERTED)
DECLARE @卷煙品牌 VARCHAR(40)
SET @卷煙品牌 = (SELECT 卷煙品牌 FROM INSERTED)
DECLARE @發賣數目 MONEY
SET @發賣數目 = (SELECT 發賣數目 FROM INSERTED)
UPDATE 卷煙庫存表
SET 庫存數目 = 庫存數目 - @發賣數目,
庫存金額 = (庫存數目 - @發賣數目)*庫存單價
WHERE 卷煙品牌 = @卷煙品牌
COMMIT TRANSACTION
GO
--請年夜家自行跟蹤[卷煙庫存表]和[卷煙發賣表]的數據變更。
--針對[卷煙發賣表],拔出第一條測試數據,該數據是正常的。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅塔山新權勢','某購貨商',10,12,1200
GO
--針對[卷煙發賣表],拔出第二條測試數據,該數據 發賣金額 不等於 發賣單價 * 發賣數目。
--觸發器將主動更負數據,使 發賣金額 等於 發賣單價 * 發賣數目。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅塔隱士為峰','某購貨商',10,22,2000
GO
--針對[卷煙發賣表],拔出第三條測試數據,該數據中的卷煙品牌在 卷煙庫存表中找不到對應。
--觸發器將報錯。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '紅河V8','某購貨商',10,60,600
GO

/*
成果集
辦事器: 新聞 50000,級別 16,狀況 1,進程 T_INSERT_卷煙發賣表,行 15
毛病!該卷煙不存在庫存,不克不及發賣。
*/
--針對[卷煙發賣表],拔出第三條測試數據,該數據中的卷煙品牌在 卷煙庫存表中庫存為0。
--觸發器將報錯。
INSERT INTO 卷煙發賣表(卷煙品牌,購貨商,發賣數目,發賣單價,發賣金額)
SELECT '玉溪','某購貨商',10,30,300
GO
/*
成果集
辦事器: 新聞 50000,級別 16,狀況 1,進程 T_INSERT_卷煙發賣表,行 29
毛病!該卷煙庫存小於等於0,不克不及發賣。
*/
--查詢數據
SELECT * FROM 卷煙庫存表
SELECT * FROM 卷煙發賣表
GO
/*
彌補:
1、本示例重要經由過程一個簡略的營業規矩完成來停止觸發器應用的解釋,詳細的要依據須要靈巧處置;
2、關於觸發器要懂得並應用好 INSERTED ,DELETED 兩個體系表;
3、本示例創立的觸發器都是 FOR INSERT ,詳細的語法可參考:
Trigger語法

CREATE TRIGGER trigger_name
ON { table | view }
[ WITH ENCRYPTION ] --用於加密觸發器
{
{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
[ { IF UPDATE ( column )
[ { AND | OR } UPDATE ( column ) ]
[ ...n ]
| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )
{ comparison_operator } column_bitmask [ ...n ]
} ]
sql_statement [ ...n ]
}
}

4、關於觸發器,還應當留意
(1)、DELETE 觸發器不克不及捕捉 TRUNCATE TABLE 語句。
(2)、觸發器中不許可以下 Transact-SQL 語句:
ALTER DATABASE CREATE DATABASE DISK INIT
DISK RESIZE DROP DATABASE LOAD DATABASE
LOAD LOG RECONFIGURE RESTORE DATABASE
RESTORE LOG
(3)、觸發器最多可以嵌套 32 層。
*/
--修正觸發器
--本質上,是將 CREATE TRIGGER ... 修正為 ALTER TRIGGER ...便可。
--刪除觸發器
DROP TRIGGER xxx
GO
--刪除測試情況
DROP TABLE 卷煙庫存表
GO
DROP TABLE 卷煙發賣表
GO
DROP TRIGGER T_INSERT_卷煙庫存表
GO
DROP TRIGGER T_INSERT_卷煙發賣表
GO
##################################################################
觸發器的基本常識和例子
:create trigger tr_name
on table/view
{for | after | instead of } [update][,][insert][,][delete]
[with encryption]
as {batch | if update (col_name) [{and|or} update (col_name)] }
解釋:
1 tr_name :觸發器稱號
2 on table/view :觸發器所感化的表。一個觸發器只能感化於一個表
3 for 和after :同義
4 after 與instead of :sql 2000新增項目afrer 與 instead of 的差別
After
在觸發事宜產生今後才被激活,只可以樹立在表上
Instead of
取代了響應的觸發事宜而被履行,既可以樹立在表上也能夠樹立在視圖上
5 insert、update、delete:激活觸發器的三種操作,可以同時履行,也可選其一
6 if update (col_name):注解所作的操尴尬刁難指定列能否有影響,有影響,則激活觸發器。另外,由於delete 操作只對行有影響,
所以假如應用delete操作就不克不及用這條語句了(固然應用也不失足,然則不克不及激活觸發器,沒意義)。
7 觸發器履行時用到的兩個特別表:deleted ,inserted
deleted 和inserted 可以說是一種特別的暫時表,是在停止激活觸發器時由體系主動生成的,其構造與觸發器感化的表構造是一
樣的,只是寄存 的數據有差別。

上面表格解釋deleted 與inserted 數據的差別
deleted 與inserted 數據的差別
Inserted
寄存停止insert和update 操作後的數據
Deleted
寄存停止delete 和update操作前的數據
留意:update 操作相當於先輩行delete 再停止insert ,所以在停止update操作時,修正前的數據拷貝一條到deleted 表中,修正後
的數據在存到觸發器感化的表的同時,也同時生成一條拷貝到insered表中
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved