使用Trigger實現Cascading的功能

2022-04-20 08:11:12 字數 2939 閱讀 6655

使用資料庫的朋友大家想必都知道,如果想要維持「一堆多」資料表資料的一致性,必須做到以下幾點:

1)插入時,外來鍵必須包含於主表(「1」對多中「1」那個表)關聯字段集合中。

2)刪除時,主表關聯欄位被刪除,其子表關聯資料也一律自動被刪除。

3)更新時,主表關聯欄位被更新,其子表關聯資料也一律自動被更新。

其實要做到這三點,最簡單的乙個做法莫過於:

1)開啟sql management studio,成功登陸之後開啟某個資料庫(展開「+」節點),並且找到「diagram」(關聯圖),匯入所需要的表。

2)從主表(「1」)滑鼠左鍵按住不放,拖拽到從表(「多」)的「外來鍵」字段。在彈出的對話方塊中分別確定設定主表和從表即將關聯的主鍵和外來鍵。

3)右鍵生成的那個關聯線,設定插入/刪除更新時候的情況:

更新和刪除規則有若干選項——其中「級聯」就是本文開頭所說的部分——「一榮俱榮,一損俱損」。

至於「插入」時的外來鍵一致性,在「強制外來鍵約束」預設設定為「是」可以得到體現(因為一旦建立了表關係,那麼外來鍵也就自動檢查必須是隸屬於主表關聯欄位的乙個元素)。

其實我們也可以採用trigger來完成同樣的任務——所謂trigger即「觸發器」(可以理解成「事件」,是乙個特定動作行為產生之後所帶來的連鎖反應)。

對於「插入」時外來鍵約束(我們假設有categories和products表,其中category主表,其id關聯於從表的products的categoryid)。trigger可以這樣寫:

create

trigger

[dbo

].[autocheck]on

[dbo

].[tb_products

]for

insert

asbegin

begin

tran

--儲存欲待插入的categoryid

declare

@newcategoryid

intselect

@newcategoryid

= categoryid from

inserted

if(select

count(*) from tb_category where id=

@newcategoryid)=

1begin

print('

成功插入!')

commit

endelse

begin

print('

插入失敗!')

rollback

tran

endend

for insert其實可以看成是類似c#或者basic.net中的inserting事件一樣——我們知道,c#中某些控制項(比如asp.net中gridview有updating和updated等事件,為了攔截插入的資料,我們可以使用該事件;該事件其中有一些引數自動記錄欲插入資料表的新資料為我們所用並處理)。自然地,該「引數」在sql中其實就是inserted表(每次插入記錄,都會生成這張臨時表,且裡邊只有一條記錄)。我們從裡邊獲取了categoryid並且在category表中做搜尋——如果找到,說明存在(可以作為外來鍵插入,否則不行)。因此還用了if……else進行判斷。為了防止錯誤插入保持資料一致性,我們必須用「事物」(begin transcation……commit……rollback)**塊把sql**封裝起來。

與此類似地還有delete和update——這裡只給出delete的級聯刪除(使用trigger完成)的示例**:

create

trigger

[dbo

].[cascadingdelete]on

[dbo

].[tb_category

]for

delete

asbegin

begin

transaction

declare

@primarykey

intselect

@primarykey

= id from

deleted

delete

from tb_products where categoryid=

@primarykey

commit

end

總而言之,sql實現的級聯新增/刪除或者更新其本質就是類似乙個內部的觸發器原理。

既然「級聯」觸發器完全可以被sql內建的「關係圖」取代,為何還是需要它呢?原因很簡單——在某些情況下sql是無法使用「級聯刪除/更新」滴。

假設有三張表category,products和order。現在category<==>order和product<==>order分別構成1對多關係(級聯刪除/更新),且category和products也構成一對多(級聯刪除/更新),此時如果使用「關係圖」拉關係設定級聯,將會觸發「多重迴圈級聯……」的問題,原因很簡單,如果可以的話,那麼刪除乙個category將附帶著刪除對應的order內容;同時刪除products內容;但是product又和order形成了級聯刪除關係,那麼當刪除乙個category,級聯刪除products的同時,order也會被級聯刪除,等於刪除了二次,資料會造成錯誤的

一般設定表級聯關係時,不允許形成這種環形級聯

但是如果你硬要這樣做,必須破壞「環」——有兩種做法:

1)刪除category和orders的級聯關係(推薦)。

2)刪除product和orders級聯關係,改用觸發器在products上實現(不推薦,因為category沒有必要直接控制orders,一般刪除category必然刪除products,而刪除products才導致order刪除,因此第一種方案最好)。

oracle 使用trigger實現主鍵自增

首先了解trigger的概念 觸發器oracle使用 觸發器概念 使用trigger實現主鍵自增 建立表 create table tb user id number primary key,user name varchar2 20 user address varchar2 30 建立tb us...

建立sequence和TRIGGER實現ID自增長

create table s if erptransferlog jobid varchar2 200 not null,startdatetime timestamp not null,enddatetime timestamp not null,usedtime number 10,0 not ...

ElementUI實現乙個省市區cascader

近期有使用到 elementui 框架,為此基於其中cascader元件做了乙個省市區級聯選擇功能。elementui cascader元件 index.js import data from pro city dis 省市區縣資料來源 const provincedata data 100000 ...