1. 程式人生 > 其它 >CodeForces-220B Little Elephant and Array

CodeForces-220B Little Elephant and Array

1 概念

觸發器是一種特殊的儲存過程,是發生在使用者對資料進行增,刪,改時自動執行的一個過程。是一種程式方式的對資料完整性控制的補充,操作更加靈活,它進一步保證資料在業務邏輯的正確性。

2 資料在非查詢的修改時,臨時表問題(只能在觸發器的程式碼中使用)

(1)inserted表:使用者向表插入新記錄資料時,(A步)先插入在系統的一個臨時表inserted表(B步)中,再從inserted表中插入到物理資料庫表中(C步)。在上面的BC步之間,還要以做一些判斷,判斷邏輯正確後,再完成C步。在BC中執行一些判斷資料邏輯正確的程式碼就是觸發器概念。如,判斷inserted臨時表的資料不符合業務邏輯需要,則取消它的C步。

(2)deleted表:要從物理表刪除記錄,並不是一次性直接刪除,而是先從物理表把要刪除的記錄存放到臨時表deleted中,在這個臨時表中再判斷業務邏輯是否正確,如果真的要刪,則才真正的物理刪除它。

無專業的updated臨時表,要更新一個記錄,把要更新的資料存放在inserted臨時表中,確保無誤後,再刪除原記錄,再在原位置插入新記錄.(刪除記錄,更新記錄,都要用於deleted臨時表。更新記錄時要同時使用deleted和inserted臨時表.

這兩個臨時表,是系統自動根據被操作的物理表的表頭結構建立的。

3 建立觸發器的格式

 Create trigger 觸發器名 on 表名/檢視名

  For  after/instead of

Insert/delete/update

As  

 Sql語句序列

針對一個物理表可以建立多個觸發器,但針對增/刪除/改同一種操作上一般只建立一個觸發器

一般觸發器是建立在對資料(表、檢視)增,刪,改時發生,不針對資料庫及非表的其它物件操作.

4 後觸發器:  for after

  先完成增/刪/改操作後,後再執行觸發器判斷.

過程:遇到了insert,delete,update時,->先操作這些語句命令(前提是不會違反以前建立資料表時各種線束)->執行觸發器

  資料操作已經完成了,再執行觸發器,如果在觸發器執行過程中,發現數據業務邏輯不正確,系統會自動反向操作上一句(撤銷上一步的更改操作)

例:針對學生表建立一個after後觸發器trigsex,當插入或修改學生表性別值時,檢查資料是否為男或女.

create trigger trigsex1 on 學生表  after insert,update as

begin

 declare @sex char(2)

 select @sex=性別 from inserted

 if(@sex<>'男' and @sex<>'女')

    begin

     raiserror('性別只能是男或女',16,1)

     rollback

    end    

end

 

insert into 學生表(學號,姓名,性別)values('10111','李四六','中')  

 select * from 學生表

update 學生表 set 性別='中' where 姓名='李九三'

解釋:先執行上面insert命令,已經把資料從inserted臨時表插入到了物理表中了,再自動執行trigsex1,才發現數據不對,再執行rollback滾回執行,把原來插入到物理表中新人刪除.----先操作再觸發,所以叫後觸發器.

例:建立一個後觸發器,當向成績表中插入或修改記錄時,如果插入或修改的資料與學生表中資料不匹配(無這個學生時,即要插入個學生學號不事先在學生表中存在),則此成績記錄無效要刪除

 create trigger trigmy1 on 成績表 after insert,update as

begin

 declare @sno char(9)

 select @sno=學號 from inserted

  if not exists(select * from 學生表 where 學號=@sno)

    begin

     raiserror('學生資訊不存在,先到學生表增加此學生',16,1)

     rollback

    end

end

insert into 成績表(學號,課程號,成績)values('001','D01',88)

 

例:限制表中職工的基本工資必須在相應工作的最低工資和最高工資之間

職工表

工號  姓名  工種號  性別  基本工資

101  張三     002   男     1900

102  李四    001   女     1200

 

工作表

工種號 工種  最低工資   最高工資

 001  車工    1500      3500

 002  鉗工    1700      3200 

…….

 Create trigger tri1 on 職工表 after insert,update

as

If exists(select * from 職工表 a inner join 工作表 b

 On a.工種號=b.工種號

  Where 基本工資 not between 最低工資 and 最高工資)

 Rolback

職工表

職工號  姓名 性別   工種號

 

工作表

工種號  工種名  最低工資   最高工資

01     管理層   6500     18000

02     普通工人 3000     10000

03     雜工     1100     2100    

 

例:教務處要限制老師隨便修改學生的已登記成績,不能將原來已經登記的不及格成績修改為及格.如果違反約束,提出警告

(建立新表時使用完整性約束無法實現)

create trigger trimy2 on 成績表 after update as

 if exists

  (select * from inserted a join deleted b on a.學號=b.學號

   where b.成績<a.成績  and b.成績<60 and a.成績>=60)

   begin

    rollback

    print '不能將不及格成績隨意修改'

   end

   

   update 成績表 set 成績=67 where 學號='2009010101'

and 課程號='103'

 

 

5  前置觸發器

 For  instead of

  當條件滿足時,使用指定的語句去替換引起觸發的邏輯錯誤語句

 也就是說,先(前)判斷條件,再操作

 

例:使用前置觸發器實現:限制表中職工的基本工作必須在相應工作的最低工資和最高工資之間

 

Create trigger trimy3 on 職工表 instead of insert as

 If not exitst

  (Select * from inserted a join 工種表 b on a.工種號=b.工種號 where 基本工資 not between 最低工資 and 最高工資)

  Insert into 職工表 select * from inserted

解釋:當不存在不滿足業務邏輯的記錄時,再把inserted臨時表的資料插入到物理表.

 使用” Insert into 職工表 select * from inserted”來代替使用者的insert語句