DML 觸發器的多行注意事項

2021-05-26 03:03:34 字數 3068 閱讀 1787

為 dml 觸發器編寫**時,請考慮導致觸發器激發的語句可能是影響多行資料(而不是單行)的單個語句。這對於 update 和 delete 觸發器很常見,因為這些語句經常影響多行。而這對於 insert 觸發器比較少見,因為基本 insert 語句僅新增單行。但是,由於 insert 觸發器可以通過 insert into (table_name) select 語句激發,所以插入許多行可能導致呼叫單個觸發器。

在下列情況下關於多行的注意事項尤為重要:dml 觸發器的功能自動重新計算乙個表中的彙總值,並將結果儲存在另乙個表中以繼續進行計數。

注意:

我們建議不要在觸發器中使用游標,因為它們可能會降低效能。若要設計乙個影響多行的觸發器,請使用基於行集的邏輯,而不要使用游標。

示例 下列示例中的 dml 觸發器用於在 adventureworks 示例資料庫的另乙個表中儲存某列的執行總計。

a. 儲存單行插入的執行總計

第一種 dml 觸發器在一行資料載入到 purchaseorderdetail 表中時適合於單行插入。insert 語句激發 dml 觸發器,新行在觸發器執行期間載入到插入的表中。update 語句讀取該行的 linetotal 列值,並將該值與 purchaseorderheader 表的 subtotal 列中的現有值相加。where 子句確保 purchaseorderdetail 表中的更新行與插入的表中 purchaseorderid 行相匹配。

複製** -- trigger is valid for single-row inserts.

use adventureworks;

gocreate trigger newpodetail

on purchasing.purchaseorderdetail

after insert as

update purchaseorderheader

set subtotal = subtotal + linetotal

from inserted

where purchaseorderheader.purchaseorderid = inserted.purchaseorderid ;

b. 儲存多行或單行插入的執行總計

對於多行插入,示例 a 中的 dml 觸發器可能不會正確執行;位於 update 語句 (subtotal + linetotal) 中賦值表示式右側的表示式只能是乙個值,而不能是乙個值列表。因此,該觸發器的作用是檢索插入的表中任意一行的值,並將該值與 purchaseorderheader 表中的現有 subtotal 值相加,以獲得特定 purchaseorderid 值。如果某個 purchaseorderid 值在插入的表中出現多次,則此操作可能無法達到預期效果。

若要正確更新 purchaseorderheader 表,必須允許對插入的表中的多行使用觸發器。可以通過使用 sum 函式達到此目的,該函式計算每個 purchaseorderid 的插入的表中許多行的總 linetotal。sum 函式包含在相關子查詢(括號中的 select 語句)中。此子查詢將為插入的表中的每個 purchaseorderid 返回乙個值,該值與 purchaseorderheader 表中的 purchaseorderid 匹配或相關。

複製** -- trigger is valid for multirow and single-row inserts.

use adventureworks;

gocreate trigger newpodetail2

on purchasing.purchaseorderdetail

after insert as

update purchaseorderheader

set subtotal = subtotal +

(select sum(linetotal)

from inserted

where purchaseorderheader.purchaseorderid

= inserted.purchaseorderid)

where purchaseorderheader.purchaseorderid in

(select purchaseorderid from inserted);

此觸發器還適合於單行插入;linetotal 值列的和為單行的和。但是,對於此觸發器,相關子查詢和 where 子句中使用的 in 運算子需要從 sql server 2005 中進行其他處理。這對於單行插入來說,是不必要的。

c. 基於插入型別儲存執行總計

可以更改觸發器以針對不同行數使用最優方法。例如,可以在觸發器邏輯中使用 @@rowcount 函式來區分單行插入和多行插入。

複製** -- trigger valid for multirow and single row inserts

-- and optimal for single row inserts.

use adventureworks;

gocreate trigger newpodetail3

on purchasing.purchaseorderdetail

for insert as

if @@rowcount = 1

begin

update purchaseorderheader

set subtotal = subtotal + linetotal

from inserted

where purchaseorderheader.purchaseorderid = inserted.purchaseorderid

endelse

begin

update purchaseorderheader

set subtotal = subtotal +

(select sum(linetotal)

from inserted

where purchaseorderheader.purchaseorderid

= inserted.purchaseorderid)

where purchaseorderheader.purchaseorderid in

(select purchaseorderid from inserted)

end;

DML觸發器觸發順序

dml觸發器觸發時,dml語句的執行順序 1 語句之前級觸發器 2 行之前級觸發器 3 語句本身 4 行之後級觸發器 5 語句之後級觸發器 例如對錶table new進行更新,使用臨時表記錄觸發器的激發順序,如 所示 語句之前級觸發器 create or replace trigger bstate...

DML觸發器的缺憾

tom說過他希望三樣東西不曾存在 觸發器,自治事務,when others 級聯刪除 級聯修改,在設計良好的系統中是不存在的 即使有,那也是小概率事件,必須專門寫一段指令碼來解決,而不是作為常規功能存在 不得不用觸發器,要麼是原系統模組化做得不夠好,要麼是不允許改動原有的 當然有時候不是不允許,而是...

DDL觸發器與DML觸發器比較

dml觸發器 要防止對資料庫架構進行某些更改。希望資料庫中發生某種情況以響應資料庫架構中的更改。要記錄資料庫架構中的更改或事件。僅在執行觸發 ddl 觸發器的 ddl 語句後,ddl 觸發器才會激發。ddl 觸發器無法作為 instead of 觸發器使用。下面的示例顯示如何使用 ddl 觸發器阻止...