1. 程式人生 > >儲存過程用到的觸發器

儲存過程用到的觸發器

例子:

CREATE TRIGGER [JL_CZLDH_update] ON [dbo].[JL_CZLDH]
FOR update
AS
--以上是命名,其中JL_CZLDH_update是觸發器的名字,dbo是表JL_CZLDH所有者,JL_CZLDH是表名
--update是當對錶JL_CZLDH進行更新的時候觸發

BEGIN
--程式開始
DECLARE @HPDH VARCHAR(50)
DECLARE @HPMC VARCHAR(50)
DECLARE @CZLDH VARCHAR(50)
declare @jaf varchar(50)
--以上定義四個字元型變數
SELECT @HPDH=HPTH,@hpmc=hpmc,@jaf=jaf,@CZLDH=CZLDH FROM INSERTED
--以上是找出對哪條記錄進行更新,並把HPTH,HPMC,JAF,CZLDH給變數@HPDH,@hpmc,@jaf,@CZLDH
UPDATE JL_MTZDH SET

[email protected],[email protected] WHERE [email protected]
UPDATE JL_MRBSC SET [email protected],[email protected] WHERE [email protected]

if @jaf='T'
UPDATE JL_CHPZL SET JAF='F' WHERE [email protected]
--以上更新想關聯的表中的具體記錄
end

SQL觸發器語法參考2007-08-23 12:02CREATE 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 ]
     }
}

1、觸發器。

  定義: 何為觸發器?在SQL Server裡面也就是對某一個表的一定的操作,觸發某種條件,從而執行的一段程式。觸發器是一個特殊的儲存過程。
  常見的觸發器有三種:分別應用於Insert , Update , Delete 事件。(SQL Server 2000定義了新的觸發器,這裡不提)

  我為什麼要使用觸發器?
    比如,這麼兩個表:
  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
    for Update   --觸發器型別--Update
  -------------------------------------------------------
  --Name:truStudent
  --func:更新BorrowRecord 的StudentID,與Student同步。
  --Use :None
  --User:System
  --Author: wp_love
  --Date : 2003-4-16
  --Memo : 臨時寫寫的,給大家作個Sample。沒有除錯阿。
  -------------------------------------------------------
  As
    if Update(StudentID)
    begin

    Update BorrowRecord
     begin

    Update BorrowRecord
      Set br.StudentID=i.StudentID
      From BorrowRecord br , Deleted d ,Inserted i
      Where br.StudentID=d.StudentID

    end    
         
  理解觸發器裡面的兩個臨時的表:Deleted , Inserted 。注意Deleted 與Inserted分別表示觸發事件的表“舊的一條記錄”和“新的一條記錄”。
  一個Update 的過程可以看作為:生成新的記錄到Inserted表,複製舊的記錄到Deleted表,然後刪除Student記錄並寫入新紀錄。

  對於2,建立一個Delete觸發器
  Create trigger trdStudent
      On Student
      for Delete
  -------------------------------------------------------
  --Name:trdStudent
  --func:同時刪除 BorrowRecord 的資料
  --Use :None
  --User:System
  --Author:
  --Date : 2003-4-16
  --Memo : 臨時寫寫的,給大家作個Sample。沒有除錯阿。
  -------------------------------------------------------
  As
    Delete BorrowRecord
    From BorrowRecord br , Delted d
    Where br.StudentID=d.StudentID

  從這兩個例子我們可以看到了觸發器的關鍵:A.2個臨時的表;B.觸發機制。
  這裡我們只講解最簡單的觸發器。複雜的容後說明。

文章引用自:

引數
trigger_name

是觸發器的名稱。觸發器名稱必須符合識別符號規則,並且在資料庫中必須唯一。可以選擇是否指定觸發器所有者名稱。

Table | view

是在其上執行觸發器的表或檢視,有時稱為觸發器表或觸發器檢視。可以選擇是否指定表或檢視的所有者名稱。

WITH ENCRYPTION

加密 syscomments 表中包含 CREATE TRIGGER 語句文字的條目。使用 WITH ENCRYPTION 可防止將觸發器作為 SQL Server 複製的一部分發布。

AFTER

指定觸發器只有在觸發 SQL 語句中指定的所有操作都已成功執行後才激發。所有的引用級聯操作和約束檢查也必須成功完成後,才能執行此觸發器。

如果僅指定 FOR 關鍵字,則 AFTER 是預設設定。

不能在檢視上定義 AFTER 觸發器。

INSTEAD OF

指定執行觸發器而不是執行觸發 SQL 語句,從而替代觸發語句的操作。

在表或檢視上,每個 INSERT、UPDATE 或 DELETE 語句最多可以定義一個 INSTEAD OF 觸發器。然而,可以在每個具有 INSTEAD OF 觸發器的檢視上定義檢視。

INSTEAD OF 觸發器不能在 WITH CHECK OPTION 的可更新檢視上定義。如果向指定了 WITH CHECK OPTION 選項的可更新檢視新增 INSTEAD OF 觸發器,SQL Server 將產生一個錯誤。使用者必須用 ALTER VIEW 刪除該選項後才能定義 INSTEAD OF 觸發器。

{ [DELETE] [,] [INSERT] [,] [UPDATE] }

是指定在表或檢視上執行哪些資料修改語句時將啟用觸發器的關鍵字。必須至少指定一個選項。在觸發器定義中允許使用以任意順序組合的這些關鍵字。如果指定的選項多於一個,需用逗號分隔這些選項。

對於 INSTEAD OF 觸發器,不允許在具有 ON DELETE 級聯操作引用關係的表上使用 DELETE 選項。同樣,也不允許在具有 ON UPDATE 級聯操作引用關係的表上使用 UPDATE 選項。

WITH APPEND

指 定應該新增現有型別的其它觸發器。只有當相容級別是 65 或更低時,才需要使用該可選子句。如果相容級別是 70 或更高,則不必使用 WITH APPEND 子句新增現有型別的其它觸發器(這是相容級別設定為 70 或更高的 CREATE TRIGGER 的預設行為)。有關更多資訊,請參見 sp_dbcmptlevel。

WITH APPEND 不能與 INSTEAD OF 觸發器一起使用,或者,如果顯式宣告 AFTER 觸發器,也不能使用該子句。只有當出於向後相容而指定 FOR 時(沒有 INSTEAD OF 或 AFTER),才能使用 WITH APPEND。以後的版本將不支援 WITH APPEND 和 FOR(將被解釋為 AFTER)。

NOT FOR REPLICATION

表示當複製程序更改觸發器所涉及的表時,不應執行該觸發器。

AS

是觸發器要執行的操作。

sql_statement

是觸發器的條件和操作。觸發器條件指定其它準則,以確定 DELETE、INSERT 或 UPDATE 語句是否導致執行觸發器操作。

當嘗試 DELETE、INSERT 或 UPDATE 操作時,Transact-SQL語句中指定的觸發器操作將生效。

觸發器可以包含任意數量和種類的 Transact-SQL 語句。觸發器旨在根據資料修改語句檢查或更改資料;它不應將資料返回給使用者。觸發器中的 Transact-SQL 語句常常包含控制流語言。CREATE TRIGGER 語句中使用幾個特殊的表:

deleted 和 inserted 是邏輯(概念)表。這些表在結構上類似於定義觸發器的表(也就是在其中嘗試使用者操作的表);這些表用於儲存使用者操作可能更改的行的舊值或新值。例如,若要檢索 deleted 表中的所有值,請使用:
SELECT *FROM deleted
如果相容級別等於 70,那麼在 DELETE、INSERT 或 UPDATE 觸發器中,SQL Server 將不允許引用 inserted 和 deleted 表中的 text、ntext 或 image 列。不能訪問 inserted 和 deleted 表中的 text、ntext 和 image 值。若要在 INSERT 或 UPDATE 觸發器中檢索新值,請將 inserted 表與原始更新表聯接。當相容級別是 65 或更低時,對 inserted 或 deleted 表中允許空值的text、ntext 或 image 列,將返回空值;如果這些列不可為空,則返回零長度字串。
當相容級別是 80 或更高時,SQL Server 允許在表或檢視上通過 INSTEAD OF 觸發器更新 text、ntext 或 image 列。

n

是表示觸發器中可以包含多條 Transact-SQL 語句的佔位符。對於 IF UPDATE (column) 語句,可以通過重複 UPDATE (column) 子句包含多列。

IF UPDATE (column)

測 試在指定的列上進行的 INSERT 或 UPDATE 操作,不能用於 DELETE 操作。可以指定多列。因為在 ON 子句中指定了表名,所以在 IF UPDATE 子句中的列名前不要包含表名。若要測試在多個列上進行的 INSERT 或 UPDATE 操作,請在第一個操作後指定單獨的 UPDATE(column) 子句。在 INSERT 操作中 IF UPDATE 將返回 TRUE 值,因為這些列插入了顯式值或隱性 (NULL) 值。

說明   IF UPDATE (column) 子句的功能等同於 IF、IF...ELSE 或 WHILE 語句,並且可以使用 BEGIN...END 語句塊。有關更多資訊,請參見控制流語言。

可以在觸發器主體中的任意位置使用 UPDATE (column)。

column

是要測試 INSERT 或 UPDATE 操作的列名。該列可以是 SQL Server 支援的任何資料型別。但是,計算列不能用於該環境中。有關更多資訊,請參見資料型別。

IF (COLUMNS_UPDATED())

測試是否插入或更新了提及的列,僅用於 INSERT 或 UPDATE 觸發器中。COLUMNS_UPDATED 返回 varbinary 位模式,表示插入或更新了表中的哪些列。

COLUMNS_UPDATED 函式以從左到右的順序返回位,最左邊的為最不重要的位。最左邊的位表示表中的第一列;向右的下一位表示第二列,依此類推。如果在表上建立的觸發器包含 8 列以上,則 COLUMNS_UPDATED 返回多個位元組,最左邊的為最不重要的位元組。在 INSERT 操作中 COLUMNS_UPDATED 將對所有列返回 TRUE 值,因為這些列插入了顯式值或隱性 (NULL) 值。

可以在觸發器主體中的任意位置使用 COLUMNS_UPDATED。

bitwise_operator

是用於比較運算的位運算子。

updated_bitmask

是整型位掩碼,表示實際更新或插入的列。例如,表 t1 包含列 C1、C2、C3、C4 和 C5。假定表 t1 上有 UPDATE 觸發器,若要檢查列 C2、C3 和 C4 是否都有更新,指定值 14;若要檢查是否只有列 C2 有更新,指定值 2。

comparison_operator

是比較運算子。使用等號 (=) 檢查 updated_bitmask 中指定的所有列是否都實際進行了更新。使用大於號 (>) 檢查 updated_bitmask 中指定的任一列或某些列是否已更新。

column_bitmask

是要檢查的列的整型位掩碼,用來檢查是否已更新或插入了這些列。

註釋
觸 發器常常用於強制業務規則和資料完整性。SQL Server 通過表建立語句(ALTER TABLE 和 CREATE TABLE)提供宣告引用完整性 (DRI);但是 DRI 不提供資料庫間的引用完整性。若要強制引用完整性(有關表的主鍵和外來鍵之間關係的規則),請使用主鍵和外來鍵約束(ALTER TABLE 和 CREATE TABLE 的 PRIMARY KEY 和 FOREIGN KEY 關鍵字)。如果觸發器表存在約束,則在 INSTEAD OF 觸發器執行之後和 AFTER 觸發器執行之前檢查這些約束。如果違反了約束,則回滾 INSTEAD OF 觸發器操作且不執行(激發)AFTER 觸發器。

可用 sp_settriggerorder 指定表上第一個和最後一個執行的 AFTER 觸發器。在表上只能為每個 INSERT、UPDATE 和 DELETE 操作指定一個第一個執行和一個最後一個執行的 AFTER 觸發器。如果同一表上還有其它 AFTER 觸發器,則這些觸發器將以隨機順序執行。

如果 ALTER TRIGGER 語句更改了第一個或最後一個觸發器,則將除去已修改觸發器上設定的第一個或最後一個特性,而且必須用 sp_settriggerorder 重置排序值。

只有當觸發 SQL 語句(包括所有與更新或刪除的物件關聯的引用級聯操作和約束檢查)成功執行後,AFTER 觸發器才會執行。AFTER 觸發器檢查觸發語句的執行效果,以及所有由觸發語句引起的 UPDATE 和 DELETE 引用級聯操作的效果。

觸發器限制
CREATE TRIGGER 必須是批處理中的第一條語句,並且只能應用到一個表中。

觸發器只能在當前的資料庫中建立,不過觸發器可以引用當前資料庫的外部物件。

如果指定觸發器所有者名稱以限定觸發器,請以相同的方式限定表名。

在同一條 CREATE TRIGGER 語句中,可以為多種使用者操作(如 INSERT 和 UPDATE)定義相同的觸發器操作。

如果一個表的外來鍵在 DELETE/UPDATE 操作上定義了級聯,則不能在該表上定義 INSTEAD OF DELETE/UPDATE 觸發器。

在觸發器內可以指定任意的 SET 語句。所選擇的 SET 選項在觸發器執行期間有效,並在觸發器執行完後恢復到以前的設定。

與 使用儲存過程一樣,當觸發器激發時,將向呼叫應用程式返回結果。若要避免由於觸發器激發而嚮應用程式返回結果,請不要包含返回結果的 SELECT 語句,也不要包含在觸發器中進行變數賦值的語句。包含向用戶返回結果的 SELECT 語句或進行變數賦值的語句的觸發器需要特殊處理;這些返回的結果必須寫入允許修改觸發器表的每個應用程式中。如果必須在觸發器中進行變數賦值,則應該在觸 發器的開頭使用 SET NOCOUNT 語句以避免返回任何結果集。

DELETE 觸發器不能捕獲 TRUNCATE TABLE 語句。儘管 TRUNCATE TABLE 語句實際上是沒有 WHERE 子句的 DELETE(它刪除所有行),但它是無日誌記錄的,因而不能執行觸發器。因為 TRUNCATE TABLE 語句的許可權預設授予表所有者且不可轉讓,所以只有表所有者才需要考慮無意中用 TRUNCATE TABLE 語句規避 DELETE 觸發器的問題。

無論有日誌記錄還是無日誌記錄,WRITETEXT 語句都不啟用觸發器。

觸發器中不允許以下 Transact-SQL 語句:

ALTER DATABASE CREATE DATABASE DISK INIT
DISK RESIZE DROP DATABASE LOAD DATABASE
LOAD LOG RECONFIGURE RESTORE DATABASE
RESTORE LOG  


說明   由於 SQL Server 不支援系統表中的使用者定義觸發器,因此建議不要在系統表中建立使用者定義觸發器。

多個觸發器
SQL Server 允許為每個資料修改事件(DELETE、INSERT 或 UPDATE)建立多個觸發器。例如,如果對已有 UPDATE 觸發器的表執行 CREATE TRIGGER FOR UPDATE,則將建立另一個更新觸發器。在早期版本中,在每個表上,每個資料修改事件(INSERT、UPDATE 或 DELETE)只允許有一個觸發器。

說明   如果觸發器名稱不同,則 CREATE TRIGGER(相容級別為 70)的預設行為是在現有的觸發器中新增其它觸發器。如果觸發器名稱相同,則 SQL Server 返回一條錯誤資訊。但是,如果相容級別等於或小於 65,則使用 CREATE TRIGGER 語句建立的新觸發器將替換同一型別的任何現有觸發器,即使觸發器名稱不同。有關更多資訊,請參見 sp_dbcmptlevel。

遞迴觸發器
當在 sp_dboption 中啟用 recursive triggers 設定時,SQL Server 還允許觸發器的遞迴呼叫。

遞迴觸發器允許發生兩種型別的遞迴:

間接遞迴


直接遞迴
使用間接遞迴時,應用程式更新表 T1,從而激發觸發器 TR1,該觸發器更新表 T2。在這種情況下,觸發器 T2 將激發並更新 T1。

使用直接遞迴時,應用程式更新表 T1,從而激發觸發器 TR1,該觸發器更新表 T1。由於表 T1 被更新,觸發器 TR1 再次激發,依此類推。

下例既使用了間接觸發器遞迴,又使用了直接觸發器遞迴。假定在表 T1 中定義了兩個更新觸發器 TR1 和 TR2。觸發器 TR1 遞迴地更新表 T1。UPDATE 語句使 TR1 和 TR2 各執行一次。而 TR1 的執行將觸發 TR1(遞迴)和 TR2 的執行。給定觸發器的 inserted 和 deleted 表只包含與喚醒呼叫觸發器的 UPDATE 語句相對應的行。

說明   只有啟用 sp_dboption 的 recursive triggers 設定,才會發生上述行為。對於為給定事件定義的多個觸發器,並沒有確定的執行順序。每個觸發器都應是自包含的。

禁用 recursive triggers 設定只能禁止直接遞迴。若要也禁用間接遞迴,請使用 sp_configure 將 nested triggers 伺服器選項設定為 0。

如果任一觸發器執行了 ROLLBACK TRANSACTION 語句,則無論巢狀級是多少,都不會進一步執行其它觸發器。

巢狀觸發器
觸發器最多可以巢狀 32 層。如果一個觸發器更改了包含另一個觸發器的表,則第二個觸發器將啟用,然後該觸發器可以再呼叫第三個觸發器,依此類推。如果鏈中任意一個觸發器引發了無限迴圈,則會超出巢狀級限制,從而導致取消觸發器。若要禁用巢狀觸發器,請用 sp_configure 將 nested triggers 選項設定為 0(關閉)。預設配置允許巢狀觸發器。如果巢狀觸發器是關閉的,則也將禁用遞迴觸發器,與 sp_dboption 的 recursive triggers 設定無關。

延遲名稱解析
SQL Server 允許 Transact-SQL 儲存過程、觸發器和批處理引用編譯時不存在的表。這種能力稱為延遲名稱解析。但是,如果 Transact-SQL 儲存過程、觸發器或批處理引用在儲存過程或觸發器中定義的表,則只有當相容級別設定(通過執行 sp_dbcmptlevel 設定)等於 65 時,才會在建立時發出警告。如果使用批處理,則在編譯時發出警告。如果引用的表不存在,將在執行時返回錯誤資訊。有關更多資訊,請參見延遲名稱解析和編譯。

許可權
CREATE TRIGGER 許可權預設授予定義觸發器的表所有者、sysadmin 固定伺服器角色成員以及 db_owner 和 db_ddladmin 固定資料庫角色成員,並且不可轉讓。

若要檢索表或檢視中的資料,使用者必須在表或檢視中擁有 SELECT 語句許可權。若要更新表或檢視的內容,使用者必須在表或檢視中擁有 INSERT、DELETE 和 UPDATE 語句許可權。

如果檢視中存在 INSTEAD OF 觸發器,使用者必須在該檢視中有 INSERT、DELETE 和 UPDATE 特權,以對該檢視發出 INSERT、DELETE 和 UPDATE 語句,而不管實際上是否在檢視上執行了這樣的操作。

示例
A. 使用帶有提醒訊息的觸發器
當有人試圖在 titles 表中新增或更改資料時,下例將向客戶端顯示一條訊息。

說明   訊息 50009 是 sysmessages 中的使用者定義訊息。有關建立使用者定義訊息的更多資訊,請參見 sp_addmessage。

USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'reminder' AND type = 'TR')   DROP TRIGGER reminderGOCREATE TRIGGER reminderON titlesFOR INSERT, UPDATE AS RAISERROR (50009, 16, 10)GO
B. 使用帶有提醒電子郵件的觸發器
當 titles 表更改時,下例將電子郵件傳送給指定的人員 (MaryM)。

USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'reminder' AND type = 'TR')   DROP TRIGGER reminderGOCREATE TRIGGER reminderON titlesFOR INSERT, UPDATE, DELETE AS   EXEC master..xp_sendmail 'MaryM',       'Don''t forget to print a report for the distributors.'GO
C. 在 employee 和 jobs 表之間使用觸發器業務規則
由於 CHECK 約束只能引用定義了列級或表級約束的列,表間的任何約束(在下例中是指業務規則)都必須定義為觸發器。

下例建立一個觸發器,當插入或更新僱員工作級別 (job_lvls) 時,該觸發器檢查指定僱員的工作級別(由此決定薪水)是否處於為該工作定義的範圍內。若要獲得適當的範圍,必須引用 jobs 表。

USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'employee_insupd' AND type = 'TR')   DROP TRIGGER employee_insupdGOCREATE TRIGGER employee_insupdON employeeFOR INSERT, UPDATEAS/* Get the range of level for this job type from the jobs table. */DECLARE @min_lvl tinyint,   @max_lvl tinyint,   @emp_lvl tinyint,   @job_id smallintSELECT @min_lvl = min_lvl,    @max_lvl = max_lvl,    @emp_lvl = i.job_lvl,   @job_id = i.job_idFROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id    JOIN jobs j ON j.job_id = i.job_idIF (@job_id = 1) and (@emp_lvl   10) BEGIN   RAISERROR ('Job id 1 expects the default level of 10.', 16, 1)   ROLLBACK TRANSACTIONENDELSEIF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)BEGIN   RAISERROR ('The level for job_id:%d should be between %d and %d.',      16, 1, @job_id, @min_lvl, @max_lvl)   ROLLBACK TRANSACTIONEND
D. 使用延遲名稱解析
下例建立兩個觸發器以說明延遲名稱解析。

USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'trig1' AND type = 'TR')   DROP TRIGGER trig1GO-- Creating a trigger on a nonexistent table.CREATE TRIGGER trig1on authorsFOR INSERT, UPDATE, DELETEAS    SELECT a.au_lname, a.au_fname, x.info    FROM authors a INNER JOIN does_not_exist x       ON a.au_id = x.au_idGO-- Here is the statement to actually see the text of the trigger.SELECT o.id, c.textFROM sysobjects o INNER JOIN syscomments c    ON o.id = c.idWHERE o.type = 'TR' and o.name = 'trig1'-- Creating a trigger on an existing table, but with a nonexistent -- column.USE pubsIF EXISTS (SELECT name FROM sysobjects      WHERE name = 'trig2' AND type = 'TR')   DROP TRIGGER trig2GOCREATE TRIGGER trig2 ON authorsFOR INSERT, UPDATEAS    DECLARE @fax varchar(12)   SELECT @fax = phone      FROM authorsGO-- Here is the statement to actually see the text of the trigger.SELECT o.id, c.textFROM sysobjects o INNER JOIN syscomments c    ON o.id = c.idWHERE o.type = 'TR' and o.name = 'trig2'
E. 使用 COLUMNS_UPDATED
下例建立兩個表:一個 employeeData 表和一個 auditEmployeeData 表。人力資源部的成員可以修改 employeeData 表,該表包含敏感的僱員薪水資訊。如果更改了僱員的社會保險號碼 (SSN)、年薪或銀行帳戶,則生成稽核記錄並插入到 auditEmployeeData 稽核表。

通過使用 COLUMNS_UPDATED() 功能,可以快速測試對這些包含敏感僱員資訊的列所做的更改。只有在試圖檢測對錶中的前 8 列所做的更改時,COLUMNS_UPDATED() 才起作用。

USE pubsIF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES   WHERE TABLE_NAME = 'employeeData')   DROP TABLE employeeDataIF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES   WHERE TABLE_NAME = 'auditEmployeeData')   DROP TABLE auditEmployeeDataGOCREATE TABLE employeeData (   emp_id int NOT NULL,   emp_bankAccountNumber char (10) NOT NULL,   emp_salary int NOT NULL,   emp_SSN char (11) NOT NULL,   emp_lname nchar (32) NOT NULL,   emp_fname nchar (32) NOT NULL,   emp_manager int NOT NULL   )GOCREATE TABLE auditEmployeeData (   audit_log_id uniqueidentifier DEFAULT NEWID(),   audit_log_type char (3) NOT NULL,   audit_emp_id int NOT NULL,   audit_emp_bankAccountNumber char (10) NULL,   audit_emp_salary int NULL,   audit_emp_SSN char (11) NULL,   audit_user sysname DEFAULT SUSER_SNAME(),   audit_changed datetime DEFAULT GETDATE()   )GOCREATE TRIGGER updEmployeeData ON employeeData FOR update AS/*Check whether columns 2, 3 or 4 has been updated. If any or all of columns 2, 3 or 4 have been changed, create an audit record. The bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14. To check if all columns 2, 3, and 4 are updated, use = 14 in place of >0 (below).*/   IF (COLUMNS_UPDATED() & 14) > 0/*Use IF (COLUMNS_UPDATED() & 14) = 14 to see if all of columns 2, 3, and 4 are updated.*/      BEGIN-- Audit OLD record.      INSERT INTO auditEmployeeData         (audit_log_type,         audit_emp_id,         audit_emp_bankAccountNumber,         audit_emp_salary,         audit_emp_SSN)         SELECT 'OLD',             del.emp_id,            del.emp_bankAccountNumber,            del.emp_salary,            del.emp_SSN         FROM deleted del-- Audit NEW record.      INSERT INTO auditEmployeeData         (audit_log_type,         audit_emp_id,         audit_emp_bankAccountNumber,         audit_emp_salary,         audit_emp_SSN)         SELECT 'NEW',            ins.emp_id,            ins.emp_bankAccountNumber,            ins.emp_salary,            ins.emp_SSN         FROM inserted ins   ENDGO/*Inserting a new employee does not cause the UPDATE trigger to fire.*/INSERT INTO employeeData   VALUES ( 101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland', 32)GO/*Updating the employee record for employee number 101 to change the salary to 51000 causes the UPDATE trigger to fire and an audit trail to be produced.*/UPDATE employeeData   SET emp_salary = 51000   WHERE emp_id = 101GOSELECT * FROM auditEmployeeDataGO/*Updating the employee record for employee number 101 to change both the bank account number and social security number (SSN) causes the UPDATE trigger to fire and an audit trail to be produced.*/UPDATE employeeData   SET emp_bankAccountNumber = '133146A0', emp_SSN = 'R-M53550M'   WHERE emp_id = 101GOSELECT * FROM auditEmployeeDataGO
F. 使用 COLUMNS_UPDATED 測試 8 列以上
如果必須測試影響到表中前 8 列以外的列的更新時,必須使用 UBSTRING 函式測試由 COLUMNS_UPDATED 返回的適當的位。下例測試影響 Northwind.dbo.Customers 表中的第 3、第 5 或第 9 列的更新。

USE NorthwindDROP TRIGGER  tr1GOCREATE TRIGGER tr1 ON CustomersFOR UPDATE AS   IF ( (SUBSTRING(COLUMNS_UPDATED(),1,1)=power(2,(3-1))      + power(2,(5-1)))       AND (SUBSTRING(COLUMNS_UPDATED(),2,1)=power(2,(1-1)))      )    PRINT 'Columns 3, 5 and 9 updated'GOUPDATE Customers    SET ContactName=ContactName,      Address=Address,      Country=CountryGO
 

相關推薦

儲存過程到的觸發器

例子: CREATE TRIGGER [JL_CZLDH_update] ON [dbo].[JL_CZLDH] FOR update AS --以上是命名,其中JL_CZLDH_update是觸發器的名字,dbo是表JL_CZLDH所有者,JL_CZLDH是表名 --upd

資料庫儲存過程觸發器,遊標,函式

MySQL5 中添加了儲存過程的支援。  大多數SQL語句都是針對一個或多個表的單條語句。並非所有的操作都這麼簡單。經常會有一個完整的操作需要多條才能完成。  儲存過程簡單來說,就是為以後的使用而儲存的一條或多條MySQL語句的集合。可將其視為批檔案。雖然他們的

mysql高階包含索引建立優化_函式_儲存過程_觸發器_及遊標

Mysql 高階部分   (1)索引(index)1 (2)檢視(view)2 (3)觸發器(trigger)6 (4)遊標(cursor)8 (5)事務(Transaction)10 (6)儲存過程(Stored Procedure)1

儲存過程觸發器的簡單學習

為什麼需要儲存過程? 在沒有使用儲存過程的資料庫應用程式中,使用者所編寫的應用程式都是從本地計算機(client)向伺服器(server)端傳送SQL程式碼來請求對資料庫中資料的增刪改差操作,伺服器對接收到的SQL程式碼進行編譯後執行,並將結果返回給client,再由客戶端的軟體

檢視,儲存過程觸發器

檢視的特點 檢視只是一種邏輯物件,是一種虛擬表,它並不是物理物件,因為檢視不佔物理儲存空間,在檢視中被查詢的表稱為檢視的基表,大多數的select語句都可以用在建立檢視中 優點:集中使用者使用的資料,掩碼資料的複雜性,簡化許可權管理以及為向其他應用程式輸出而重新組織資料等等 語法

Oracle 儲存過程觸發器,事務,鎖

部落格園 首頁 新隨筆 聯絡 管理 訂閱 隨筆- 75  文章- 0  評論- 0  Oracle 儲存過程,觸發器,事務,鎖 1.1儲存過程   儲存過程是一種命名的PL/SQL程式塊,他可以有引數,也可以有若干

mysql 檢視,事務,儲存過程觸發器

一 檢視 檢視是一個虛擬表(非真實存在),是跑到記憶體中的表,真實表是硬碟上的表。使用檢視我們可以把查詢過程中的臨時表摘出來,儲存下來,用檢視去實現,這樣以後再想操作該臨時表的資料時就無需重寫複雜的sql了,直接去檢視中查詢即可,但檢視有明顯地效率問題,並且檢視是存放在資料庫中的,如果我們程式中使用的sql

MySQL(四)檢視,儲存過程觸發器

一:檢視 什麼是檢視? 檢視(View)是一種虛擬存在的表,對於使用檢視的使用者來說基本上是透明的。檢視並 不在資料庫中實際存在,行和列資料來自定義檢視的查詢中使用的表,並且是在使用檢視時 動態生成的 檢視的優點? 簡單:使用檢視的使用者完全不需要關心後面對應的表的

sql server事務 鎖 儲存過程 索引 觸發器

1.事務:保證一個多操作的事情全部完成,否則回到做之前的狀態 begin try begin tran–設定反悔點,開啟事務 delete from UserInfo where UserId>5 delete from ClassInfo commit tran–不反悔,提交事務 e

【轉】MySQL資料庫 外來鍵、檢視、儲存過程觸發器的優缺點

https://www.yiibai.com/mysql/introduction-sql-views.html 檢視 使用資料庫檢視的優點 資料庫檢視允許簡化複雜查詢:資料庫檢視由與許多基礎表相關聯的SQL語句定義。 您可以使用資料庫檢視來隱藏終端使用者和外部應用

MYSQL資料庫實驗(儲存過程觸發器)

個人配置說明:5.7.24 MySQL Community Server (GPL),環境CentOS 7 1.MYSQL 不支援語句觸發(for each statement),只支援行觸發(for each row,新舊資料通過關鍵字new和old區別) 實驗: 資料庫

MySql中的儲存過程觸發器筆記

#表結構 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varchar(100) DEFAULT NULL, `user_type` tinyint(4) DEFAULT NULL, `

儲存過程到的表、分組、排序、聯結

查詢儲存過程用到的表,並進行分組、排序、聯結: 1 SELECT 2 REFERENCED_OWNER, 3 REFERENCED_NAME, 4 LISTAGG(XH||'>'||NAME,',') WITHIN GROUP(ORDER BY

MySQL儲存過程觸發器的設計與使用

資料庫中的程式邏輯 資料庫程式邏輯與PHP程式邏輯的分體設計原則: 所有的資料庫操作都可以放到PHP程式碼中實現。並且,在 MySQL5.0釋出之前,幾乎所有的PHP與MySQL結合的例項都是這樣做的。 MySQL5.0提供了對觸發器和儲存過程的支援,才使得將程式邏輯放入資料庫中的實現成

利用儲存過程觸發器來管理資料庫

本文主要介紹如何在資料庫後臺利用儲存過程,觸發器來管理資料庫的技術,並以Delphi做前臺,SQL Server做後臺的模式給出具體的實現程式碼。 一、SQL互動式資料庫查詢語言 互動式資料庫查詢語言SQL中有關表操作基本的SQL語句有如下四種:(下面分別出給四種語句的語法形式及其說明) (1)查詢表命令

從機房重構中學習資料庫——儲存過程觸發器

      開門見山,我也是在機房中學習使用儲存過程,看來大家的部落格,慢慢的使用,接觸了一段時間還是有點模糊。簡單總結一下。                                    

【機房重構】——儲存過程觸發器

          引言      在上一篇部落格中給大家介紹了觸發器的作用,那麼我在這篇部落格中給大家介紹一下儲存過程的知識,觸發器和儲存過程非常的相似,所以給大家介紹完儲存過程以後會通過對比這兩塊

利用navicat建立儲存過程觸發器和使用遊標的簡單例項

建立儲存過程和觸發器 1、建表 首先先建兩張表(users表和number表),具體設計如下圖: 2、儲存過程 寫一個儲存過程,往users表中插入資料,建立過程如下:     程式碼如下: BEGIN #Routine body goes here... d

ORACLE PL/SQL語法應用:遊標,儲存過程觸發器,函式

--遊標 --do while迴圈 declare    cursor c is select * from t_t_student order by id;   v_record c%rowtype

oracle 遊標,函式 function , 儲存過程 PROCEDURE , 觸發器 Trigger

1、 ORACLE函式定義 function uf_execute_sql(as_where varchar2, as_sql varchar2) return varchar2 is v_ret varchar2(30); begin execute immediate as_sql into v_ret