SQL Server 2008触发器错误

时间:2013-06-27 18:27:09

标签: sql sql-server sql-server-2008 triggers

我需要一些数据库触发器的帮助,但我无法正常工作。披露:我不是一名DBA,也没有任何专业知识,但我的任务是完成这项任务。

那说,这是问题陈述:

我有一个包含几个表的数据库,我们想跟踪更新/插入/删除。触发器应该捕获某些列的“之前”和“之后”值,同时获取一些其他信息(如下所述)并将它们添加到versioncontrol表中。

我根据各种网站上提供的教程和其他信息整理了我认为应该工作的内容,但无论我在尝试创建触发器时做什么,它总是会抛出错误:

  

Msg 311,Level 16,State 1,Procedure tr_taskconstructs_U,Line 38
  不能在'inserted'和'deleted'表中使用text,ntext或image列。

我正在应用触发器的表的列布局非常简单:

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

它始终因上述错误而失败。我尝试使用相同的结果更改变量的数据类型等。我已经尝试评论几乎所有内容,它也有同样的错误。我显然错过了一些东西,但我无法弄清楚是什么。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:5)

更改表以使用nvarchar(max)数据类型。无论如何都要弃用Ntext,不应该继续使用

答案 1 :(得分:1)

就像在另一个答案ntext中所说的那样,与textimage一起使用的是不推荐使用的数据类型,而触发器无法真正使用。它们将在未来版本的SQL Server中删除,因此您最好的解决方案是将它们分别更改为NVARCHAR(MAX)VARCHAR(MAX)VARBINARY(MAX)

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

但是,如果您现在不可能 - INSTEAD OF触发器可以与它们一起使用,那么您可以尝试拦截更新并从触发器执行它们,在此过程中填充您的日志表。

但是,在我向您展示示例之前,我必须指出您在现有触发器中存在的大错误 - 您已经编写了仅适用于来自{{1}的单行的查询这不好,因为INSERTED当时通常可以更新1行。即使你的应用程序不是设计允许它,你也不应该写入触发器,因为它总是单行。

所以你的触发器应该是这样的: (如果/更改该列后,应该看起来像这样)

UPDATE

现在,对于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 TRIGGER:

INSTEAD OF

<强> SQLFiddle DEMO