触发器内的光标不起作用

时间:2010-07-29 07:04:25

标签: sql-server

USE [ddb]
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[requeststrigger]
ON [dbo].[requests]
AFTER INSERT,UPDATE
AS
BEGIN
DECLARE @email VARCHAR(400);
DECLARE @firstname VARCHAR(400);
DECLARE @requestno VARCHAR(400);
DECLARE @lastname VARCHAR(400);
DECLARE @statusid INT;
DECLARE thecursor CURSOR FOR SELECT inserted.requestno,contacts.firstname,contacts.lastname,contacts.email FROM request_contacts,contacts,inserted WHERE request_contacts.requestid=inserted.requestid AND contacts.contactid=request_contacts.contactid AND request_contacts.notification=1 AND contacts.notification=1;

SET @statusid = (SELECT statusid FROM inserted);

IF @statusid = 4 AND @statusid <> (SELECT statusid FROM deleted)
BEGIN

SET NOCOUNT ON
SET ARITHABORT ON
OPEN thecursor;

    FETCH NEXT FROM thecursor
    INTO @requestno,@firstname,@lastname,@email

    WHILE @@FETCH_STATUS = 0
    BEGIN

        EXEC MAIL_SEND @email,@firstname,@requestno,@lastname;

    FETCH NEXT FROM thecursor
    INTO @requestno,@firstname,@lastname,@email

    END
CLOSE thecursor;

DEALLOCATE thecursor

SET NOCOUNT OFF
END

END

这只会使整个UPDATE / INSERT不起作用。当我删除游标声明时,它的工作原理。光标只是从一个表中选择一个字段,该表存在于名为“contacts”的同一个数据库中。有什么问题?

1 个答案:

答案 0 :(得分:2)

您是否准备考虑修改您的设计?你在这里尝试的东西似乎有几个问题。

触发器不一定是进行这种逐行操作的最佳位置,因为它与源表的更改一致地执行,并且会对系统的性能产生负面影响。

此外,您现有的代码仅对批处理中的单行评估statusid,但从逻辑上讲,它可以在一批更新中设置为多个值。

更强大的方法可能是将应生成MAIL_SEND操作的行插入到排队表中,计划作业可以从中挑选行并执行MAIL_SEND,设置标志以便每项操作只进行一次。

这会简化你对插入的触发器 - 那里不需要游标(尽管在sechduled作业中你仍然需要某种循环)。