存储过程和触发器

时间:2011-01-11 00:49:27

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

我有一个任务 - 创建更新触发器,它可以处理实际的表数据更改(不只是使用相同的值进行更新)。为此,我创建了复制表,然后开始将更新的行与旧的复制行进行比较。当触发器完成时,需要实现副本:

UPDATE CopyTable SET
    id = s.id,
    -- many, many fields
FROM MainTable s WHERE s.id IN (SELECT [id] FROM INSERTED)
                 AND CopyTable.id = s.id;

我不喜欢在触发器中使用这个丑陋的代码,所以我将其解压缩到存储过程:

CREATE PROCEDURE UpdateCopy AS
BEGIN
UPDATE CopyTable SET
    id = s.id,
    -- many, many fields
    FROM MainTable s WHERE s.id IN (SELECT [id] FROM INSERTED)
    AND CopyTable.id = s.id;
END

结果是 - 无效的对象名称“INSERTED”。我该如何解决这个问题?

此致

3 个答案:

答案 0 :(得分:4)

将代码保留在触发器中。 INSERTED是仅在触发器代码中可用的伪表。 尝试传递此伪表值,它可能包含大量条目。

这是T-SQL,一种声明性数据访问语言。它不是您的普通程序编程语言。像“代码重用”这样的常识不适用于SQL,它只会导致性能问题。将代码保留在它所属的触发器中。为了便于重新分解,通过一些代码生成工具生成触发器,以便您可以轻松地重构触发器。

答案 1 :(得分:2)

问题是INSERTED仅在触发期间可用

- 触发更改以构建ID的列表

DECLARE @idStack VARCHAR(max)
SET @idStack=','
SELECT @idStack=@idStack+ltrim(str(id))+',' FROM INSERTED

- 触发更改以调用存储过程

EXEC updateCopy(@idStack)

- 以逗号分隔的ID列表

的过程
CREATE PROCEDURE UpdateCopy(@IDLIST VARCHAR(max)) AS
BEGIN
UPDATE CopyTable SET
    id = s.id,
    -- many, many fields

    FROM MainTable s WHERE charindex(','+ltrim(str(s.id))+',',@idList) > 0
    AND CopyTable.id = s.id;
END

性能不会很好,但应该让你做你想做的事。

只需即时输入,但应运行正常

答案 2 :(得分:0)

真正的问题是“如何在存储过程中传递GUID数组?”或者,更广泛的,“如何在存储过程中传递数组?”。

以下是答案:

http://www.sommarskog.se/arrays-in-sql-2005.html

http://www.sommarskog.se/arrays-in-sql-2008.html