Sql Server 觸發器


/*
SQL Server觸發器
  1.什么是觸發器
    觸發器是一種特殊類型的存儲過程,因為它和存儲過程有一樣的特征,都是預用寫好的Sql命令存儲在SqlServer服務器中。
	觸發器在指定的表中的數據發生變化(insert/update/delete)的時候會自動執行。它與存儲過程的區別也在此,因為存儲過程是需要我們用命令去調用的。
    觸發器一般用在比check約束更加復雜的約束上面。

	注意:觸發器本身就是一個事務,所以在觸發器里面可以對修改數據進行一些特殊的檢查。如果不滿足可以利用事務回滾,撤銷操作。

  2.觸發器分類
    DML觸發器和DDL觸發器。

	DML觸發器:
	當數據庫中表中的數據發生變化時,包括insert,update,delete任意操作,如果我們對該表寫了對應的DML觸發器,那么該觸發器將自動執行。
	DML觸發器的主要作用在於強制執行業 務規則,以及擴展Sql Server約束,默認值等。因為我們知道約束只能約束同一個表中的數據,而觸發器中則可以執行任意Sql命令。
    例子:我們想要在送貨后減少庫存的數量,那我們就可以在送貨單的表上寫update觸發器,用來減少庫存的數量。

	DDL觸發器:
	它是Sql Server2005新增的觸發器,主要用於審核與規范對數據庫中表,觸發器,視圖等結構上的操作。比如在修改表,修改列,新增表,新增列等。
	它在數據庫結構發生變化時執行,我們主要用它來記錄數據庫的修改過程,以及限制程序員對數據庫的修改,比如不允許刪除某些指定表等。

    DML觸發器:
	   1.after觸發器(之后觸發)
	       a.insert觸發器
		   b.update觸發器
		   c.delete觸發器

	   2.insert of 觸發器 之前觸發

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

  3.觸發器有兩個非常特殊,非常重要的兩個表。
    insetred:插入表
	deleted:刪除表
	這兩個是邏輯表,也是虛表。由系統在內存中自動創建這兩張表,這兩張表不會存儲在數據庫中,而且這兩張表都是只讀的。這兩張表的結果總是與被
	觸發器應用的表的結構相同。當觸發器完成后,這兩表將會被刪除。

	Inserted表的數據是插入或是修改后的數據,而deleted表的數據是更新前的或是刪除的數據。


  4.編碼實現
    業務邏輯:有水果銷售表和水果庫存表,
	   */
--創建表

create table FruitsSaleTable
(
FruitsName varchar(20) primary key not null,  --水果名稱
Supplier varchar(50),  --供貨商
SaleNumber int,  --銷售數量
SaleUnitPrice money,  --單價
SaleTotalSum money   --銷售總金額
)

insert into FruitsSaleTable(FruitsName,Supplier,SaleNumber,SaleUnitPrice,SaleTotalSum)
values('冰糖雪梨','B',20,10,200)

create table FruitsStock
(
FruitsName varchar(20) primary key not null,  --水果名稱
StockNumber int,       --庫存數量
StockUnitPrice money,  --庫存單價
StockTotalSum money    --庫存總金額
)


/*
Insert:
首先我們在庫存表(FruitsStock)中創建一個Insert觸發器,
目的:1.庫存總金額=庫存數量*庫存單價 這個等式成立
      2.確保收貨時 “庫存數量”>0  不然收貨動作將毫無意義
*/

create trigger I_insert_FruitsStock  --創建觸發器
on FruitsStock   --作用那張表
for insert    --觸發條件
as
--提交事務
begin transaction 

--判斷收貨庫存是否>0
if not exists
(
select StockNumber from FruitsStock where FruitsName in (select FruitsName from inserted) and StockNumber >0
)
begin
--不滿足條件,提示
raiserror('錯誤,收貨數量不能小於0',16,1)

--事務回滾
rollback
return 
end

--條件滿足,強制執行SQL,保證業務邏輯
update FruitsStock set StockTotalSum = StockNumber * StockUnitPrice 
where FruitsName in (select FruitsName from inserted)

--提交事務
commit transaction
go

--測試觸發器
--1.數據都正確
insert into FruitsStock
(FruitsName,StockNumber,StockUnitPrice,StockTotalSum)
values('蘋果',50,10,500)

/*
結果:OK
(1 行受影響)
*/

--2.庫存總金額<>庫存數量*庫存單件
insert into FruitsStock
(FruitsName,StockNumber,StockUnitPrice,StockTotalSum)
values('冰糖雪梨',30,10,100)

/*
結果:OK
(1 行受影響)
查詢結果可的:觸發器自動進行計算,結果中顯示正確的庫存總金額
*/

--3.當收貨數量為<=0時
insert into FruitsStock
(FruitsName,StockNumber,StockUnitPrice,StockTotalSum)
values('藍莓',0,10,100)

/*
結果:OK
消息 50000,級別 16,狀態 1,過程 I_insert_FruitsStock,第 138 行
錯誤,收貨數量不能小於0
消息 3609,級別 16,狀態 1,第 124 行
事務在觸發器中結束。批處理已中止。
*/


/*
update:
首先我們在銷售表(FruitsSaleTable)中創建一個update觸發器,
業務邏輯:更改銷售價格,銷售總金額一起改變
*/

create trigger U_update_FruitsSaleTable
on FruitsSaleTable
for update 
as

if update(SaleUnitPrice)
declare @price money  --更改后的銷售價格
--提交事務
begin transaction
select @price=SaleUnitPrice from  FruitsSaleTable where FruitsName in (select FruitsName from inserted)
--begin
--if(@price<=0)
-- print'價格修改錯誤'
-- rollback
-- return 
-- end
update FruitsSaleTable set SaleTotalSum =SaleNumber * @price where FruitsName in (select FruitsName from inserted)

commit transaction
go


/*
update觸發器測試
*/
update FruitsSaleTable set SaleUnitPrice=7 where FruitsName='蘋果'

/*
結果:
(1 行受影響)
*/


/*
delete觸發器:
業務邏輯:刪除庫存表中數據時同時刪除銷售表
*/

create trigger D_delete_FruitsStock
on FruitsStock
for delete
as
begin
delete FruitsStock from FruitsStock fs,deleted d where fs.FruitsName=d.FruitsName
delete FruitsSaleTable from FruitsSaleTable st,deleted d where st.FruitsName=d.FruitsName
end
go



/*
delete觸發器
(0 行受影響)

(1 行受影響)
*/

delete from FruitsStock where FruitsName='冰糖雪梨'

select * from FruitsStock

select * from FruitsSaleTable


/*
寫的比較簡單,本人也處於學習階段,有錯誤的地方希望可以指點一下。
*/

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM