繁体   English   中英

SQL Server 2008触发错误

[英]SQL Server 2008 Trigger Errors

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

也就是说,这是问题陈述:

我有一个包含一些表的数据库,我们希望跟踪这些表的更新/插入/删除。 触发器应捕获某些列的“ before”和“ after”值,并结合一些附加信息(如下所述)并将它们添加到versioncontrol表中。

我已经根据教程和其他网站上的其他信息整理了我认为应该起作用的内容,但是无论如何尝试创建触发器,它总是会引发错误:

消息311,级别16,状态1,过程tr_taskconstructs_U,第38行
不能在“已插入”和“已删除”表中使用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

它总是会因上述错误而失败。 我尝试更改变量等的数据类型,但结果相同。 我尝试注释掉几乎所有内容,并且也有相同的错误。 我显然缺少了一些东西,但无法弄清楚是什么。

任何帮助,将不胜感激。

更改表以使用nvarchar(max)数据类型代替。 无论如何,Ntext已被弃用,今后不应该使用

就像在另一个答案中所说的, ntexttextimage都是已过时的数据类型,触发器无法真正使用它。 对于将来的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演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM