2014-02-06 72 views
0

我在表上有一個SQL觸發器,插入,更新和刪除後會觸發。MSSQL觸發器 - 問題

我將所有受影響的記錄插入單獨的物理表中,其中的代碼定義了更新的狀態。以下代碼片段是定義的觸發器。

CREATE TRIGGER [dbo].[DATA_CACHE] 
    ON [dbo].[DATA_USAGE] 
for Insert,Update,Delete 
AS 
BEGIN 
    if(select COUNT(*) from inserted)>0 
    begin 
     if (select COUNT(*) from deleted)>0 
     BEGIN 
      --update 
      INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
      SELECT 2, ins.ID, ins.DATE, ins.COUNT 
      from inserted ins 
     END 
     else 
     begin 
      -- insert 
      INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
      SELECT 1, ins.ID, ins.DATE, ins.COUNT 
      from inserted ins 
     end 
    END 
    else 
    BEGIN 
     -- delete 
     INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
     SELECT 3, del.ID, del.DATE, del.COUNT 
     from deleted del 
    end 
END 
SELECT * FROM CACHE_UPDATE_TABLE 

正如你可以在上面看到觸發了我誤觸發後添加一個額外的語句,從目標選擇表中所有的值。這個語句是在定義的觸發器之後,但是當我試圖改變觸發器時,通過右鍵點擊觸發器並選擇修改,它也向我展示了觸發器結束塊之後的select語句。

這是否意味着,每次觸發器被觸發時,這個select語句都會執行?這是我的第一個問題(問題A) - 可能是一個愚蠢的問題,但我對此有點困惑。

我的第二個問題是(問題B)我遇到了CACHE_UPDATE_TABLE鎖定問題,這可能是鎖定的原因嗎?還有一個SQL作業每運行一分鐘檢查CACHE_UPDATE_TABLE表,然後執行一些操作(鏈接服務器相關),並在完成後從CACHE_UPDATE_TABLE刪除這些記錄。鎖定問題可能是因爲這個?如果是這樣,我該如何反擊呢?

我的第三個問題是(問題C)這是使用觸發器執行此操作的最佳方式,還是我可以以其他方式執行此操作?觸發器是否正確定義?

- 任何幫助將不勝感激...謝謝。

+0

你有很多的問題,在那裏這就是爲什麼你還沒有收到任何答案。例如,我可以部分地回答A並完全回答C,但不是B. – OGHaza

回答

1

你已經得到了很多在那裏不同的問題,這可能是爲什麼您沒有收到任何答案,但我將我所能。 A)這實際上是一個非常有趣的問題。我會假設它什麼都不會做 - 它會在你創建觸發器時被執行,但不會成爲觸發器的一部分 - 但是我注意到之前有過奇怪的行爲,所以我使用一個簡單的存儲過程進行了測試:

CREATE PROCEDURE dbo.test (@i INT) AS 
BEGIN 
    SELECT @i 
END; 
SELECT 'hi' 
GO 

執行存儲過程導致SELECT 'hi'火還有SELECT @i。對於你的問題,我仍然沒有答案,但是當你僅僅因爲這個原因創建它時,我肯定會確保不要在觸發器外面有任何雜散SQL。

我剛剛調查了這一點,顯然存儲過程的末尾是第一個GO在過程之後的任何地方(如果不使用SQL Server,它會自動添加到最後)。所以你可以在END之後定義你的整個過程 - 你仍然可以使用這些參數。

這似乎是因爲BEGINEND不是存儲過程定義的一個必要組成部分 - 它們實際上並不表示開始和存儲過程的結束,他們只是一個無關的BEGIN...END塊喜歡你可能會提出和IF聲明。您可以在程序定義中儘可能多地使用BEGIN...END塊,或者根本沒有。

C)我肯定會改變你的觸發器。通過組合3個觸發器而不重複使用任何代碼,您已經大幅複雜化了它。結合INSERT,UPDATEDELETE觸發器的唯一原因是,您不必重複代碼。你應該:

  • 有3個單獨的觸發器,每個觸發器只包含相關的INSERT - 這樣你可以刪除所有的條件邏輯。
  • 將它們放在一起,但僅使用一些條件邏輯編制CODE並且只有1個INSERT語句。

我會忍不住去與3個獨立的觸發器,或者至少一個獨立出來的刪除觸發器,然後在INSERT/UPDATE觸發使用CASE del.ID IS NULL THEN 1 ELSE 2 ENDCODE。但是你可以用(未經測試),將它們組合起來:

INSERT INTO CACHE_UPDATE_TABLE (CODE, ID, DATE, COUNT) 
SELECT CASE WHEN del.ID IS NULL THEN 1 
      WHEN ins.ID IS NULL THEN 3 
      ELSE 2 END 
    ,ISNULL(ins.ID, del.ID) 
    ,ISNULL(ins.DATE, del.DATE) 
    ,ISNULL(ins.COUNT, del.COUNT) 
FROM deleted del 
FULL OUTER JOIN inserted ins ON del.ID = ins.ID 
+0

感謝您的回覆。加入觸發器似乎仍然很昂貴。在我的觸發器中,我只有兩個條件,每次都會檢查並插入。就性能而言,我不認爲這會很昂貴。我可能是錯的,我會測試一下。 但是,你的程序反應的方式非常奇怪,在END語句之後,無論你添加什麼,它似乎都會被執行。 –

+0

在這些情況下,這兩者都不會很昂貴,但是'IF'語句阻止了好的查詢計劃被緩存,所以我敢打賭'JOIN'會表現得更好 - 只有知道的方法纔是基準測試。無疑,最好的性能來自3個獨立的觸發器,它們都會緩存理想的執行計劃。 – OGHaza

+0

編輯我的答案,多一點關於A的信息 – OGHaza

0

只是刪除

SELECT * FROM CACHE_UPDATE_TABLE 
+0

Dude,我已經將其刪除了......我想知道爲什麼它在觸發器外部執行。 –