2013-06-27 80 views
0

我需要一些數據庫觸發器的幫助,但我無法正常工作。披露:我不是一個DBA,並且不要求任何專業知識,但我一直在負責完成這一操作..SQL Server 2008觸發器錯誤

也就是說,這裏的問題陳述:

我有一個數據庫我們想跟蹤更新/插入/刪除的幾個表。觸發器應該捕捉某些列的「之前」和「之後」值,同時附帶一些附加信息(如下所述)並將它們添加到​​表中。

我已經把我認爲應該工作基礎上的教程和其他信息可在各種網站,但無論我做什麼,當我嘗試創建觸發器它總是拋出一個錯誤:

Msg 311, Level 16, State 1, Procedure tr_taskconstructs_U, Line 38
Cannot use text, ntext, or image columns in the 'inserted' and 'deleted' tables.

爲我申請的觸發器表中的列布局很簡單:

ResourceID (PK, nvarchar(38)) 
AML (ntext, null) 

我要趕更改AML列並插入轉變爲一個表,如下所示:

id (int, not null), 
ResourceID (nvarchar(38)), 
TableName (nvarchar(50)), 
DateTime (datetime), 
Type (varchar(20)), 
Before (ntext), 
After (ntext) 

我的代碼如下:

CREATE TRIGGER tr_taskconstructs_U ON taskconstructs AFTER UPDATE 
AS 
BEGIN 

SET NOCOUNT ON; 

    DECLARE @before nvarchar(max), 
     @after nvarchar(max), 
     @resource nvarchar(50) 

IF UPDATE(AML) 
BEGIN 
    SELECT @before = d.AML, 
      @after = i.AML, 
      @resource = d.ResourceID 
    FROM inserted i 
     INNER JOIN deleted d on d.ResourceID = i.ResourceID 

    INSERT INTO versioncontrol 
    VALUES (@resource, 'taskconstructs', GetDate(), 'Update', @before, @after) 

END 

END 
GO 

它總是失敗,上面提到的錯誤。我試着改變變量的數據類型等,結果相同。我試過評論幾乎所有的東西,它也有同樣的錯誤。我顯然缺少一些東西,但我無法弄清楚什麼。

任何幫助,將不勝感激。

回答

1

就像在其他回答ntext中說的,以及textimage是不贊成使用的數據類型,這些觸發器不能真正起作用。他們將被刪除的SQL Server的未來版本,所以你最好的解決辦法是將它們分別改爲NVARCHAR(MAX)VARCHAR(MAX)VARBINARY(MAX)

http://msdn.microsoft.com/en-us/library/ms189799.aspx

但是,如果這不是在此刻爲你的可能性 - INSTEAD OF觸發與他們合作,所以你可以嘗試攔截更新和觸發做他們,盡顯你的日誌表的過程。

但是,之前我給你舉例說,你在你現有的觸發我必須指出一個很大的錯誤 - 你已經寫了上單列從INSERTED只能查詢這是不好的UPDATE能通常更新時間超過1行。即使你的應用程序沒有被設計爲允許它,你也不應該寫觸發器,因爲它總是會是單行的。

所以,你的觸發器應該是這個樣子的: (應該是這樣的,如果/當你改變了該列)現在

CREATE TRIGGER tr_taskconstructs_U ON taskconstructs AFTER UPDATE 
AS 
BEGIN 

SET NOCOUNT ON; 

IF UPDATE(AML) 
BEGIN 

    INSERT INTO versioncontrol 
    SELECT ResourceID, 'taskconstructs', GetDate(), 'Update'. d.AML, i.AML 
    FROM inserted i 
    INNER JOIN deleted d on d.ResourceID = i.ResourceID 

END 

END 
GO 

,爲INSTEAD OF TRIGGER:

CREATE TRIGGER tr_taskconstructs_U ON taskconstructs INSTEAD OF UPDATE 
AS 
BEGIN 

    --insert log 
    INSERT INTO versioncontrol 
    SELECT i.ResourceID, 'taskconstructs', GetDate(), 'Update', d.AML, i.AML 
    FROM inserted i 
    INNER JOIN taskconstructs d on d.ResourceID = i.ResourceID 

    --update actual data 
    UPDATE t 
    SET t.AML = i.AML 
    from taskconstructs t 
    INNER JOIN INSERTED i ON i.ResourceID = t.ResourceID 

END 
GO 

SQLFiddle DEMO

+0

@Nenand - 您對INSTEAD OF UPDATE的解決方案非常完美。由於該應用程序是商業應用程序,因此我將運行此應用程序,並且我不知道如何更改他們的某個系統表會影響應用程序。同時也非常感謝你在多行上的發現......你讓我看起來像英雄。 :) – user2093445

+0

@ user2093445 YW! :)至於改變列類型 - 雖然我不會建議你做任何事情,而不先諮詢任何負責非生產環境中的應用程序和測試的人。 - 我認爲從'ntext'切換到'nvarchar(max)'應該沒有任何問題,而不需要改變應用程序。 http://www.sqlfiddle.com/#!6/2d9b1/2 –

5

更改表以改爲使用nvarchar(max)數據類型。 Ntext已被棄用,不應該繼續使用

+0

感謝SQLMenace - 我已經更新了versioncontrol表中的列使用varchar或nvarchar,但我仍然得到相同的錯誤。 – user2093445

+1

@ user2093445您需要更改'taskconstructs'表。觸發器無法監控'ntext'列上的更改 –

+0

啊,我明白了。我在版本控制表上更改了它。我不確定是否可以更改任務構造表,因爲該應用程序是商業應用程序,我無法更改源代碼。如果我無法更改源表格,是否有任何選項? – user2093445