[英]SQL Server trigger's cursor is not working
I created a cursor inside a trigger and it is not working properly. 我在触发器内创建了一个游标,但它无法正常工作。 Please help me fix it
请帮我解决
Create trigger Posts_Raw_To_Queue_Trigger ON SendNotificationPostsRaw FOR INSERT
AS
BEGIN
DECLARE @PostID uniqueidentifier
DECLARE @UserID uniqueidentifier
DECLARE @ProfID int
DECLARE @Email nvarchar(100)
DECLARE @CreationTime datetime
DECLARE @SpecialityID int
SELECT @ProfID= ProfessionalID,@Email= Email from Professionals where UserID=@UserID
SELECT @PostID = I.PostID,@UserID = I.UserID ,@CreationTime =I.CreationTime FROM INSERTED I
DECLARE post_relation_cursor CURSOR FOR select CategoryId from PostCategoryRelations where PostId=@PostID;
OPEN post_relation_cursor;
FETCH NEXT FROM post_relation_cursor INTO @SpecialityID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO SendNotificationPostsQueue (UserID,PostID,SpecialityID,TemplateID,CreationTime,SendTime,JSONParameters) Values(@UserID,@PostID,1,1,'04/11/2013','04/11/2013','')
FETCH NEXT FROM post_relation_cursor INTO @SpecialityID;
END;
CLOSE post_relation_cursor;
DEALLOCATE post_relation_cursor;
END
If I remove cursor and insert dummy values into SendNotificationPostsQueue
, it works. 如果我删除游标并将虚拟值插入
SendNotificationPostsQueue
,那么它将起作用。 So there is problem with my cursor... Please tell me why cursor is not working? 所以我的光标有问题...请告诉我为什么光标不起作用?
It doesn't appear that you need to use a cursor at all and would be better off not using one in almost all cases. 似乎根本不需要使用游标,最好不要在几乎所有情况下都使用游标。 Simply replace the body of your trigger (the part between begin and end) with a standard insert:
只需用标准插入件替换触发器的主体(开始和结束之间的部分)即可:
INSERT INTO SendNotificationPostsQueue (UserID,PostID,SpecialityID,TemplateID,CreationTime,SendTime,JSONParameters)
SELECT
i.UserID,
i.PostID,
1,
1,
'04/11/2013', -- Might want i.CreationTime or current_timestamp
'04/11/2013',
''
FROM INSERTED i
-- possibly want "LEFT JOIN Professionals p on i.UserID = p.UserID" here to grab other info
Note how I am not using the values
clause of an insert which can only insert one row. 请注意我如何不使用只能插入一行的插入的
values
子句。 I'm putting a select statement as part of the insert, thus inserting as many rows as the select returns. 我将select语句作为插入的一部分,从而插入了与select返回一样多的行。 This means that we don't need to use a cursor, and don't need a bunch of variables to power the cursor.
这意味着我们不需要使用游标,也不需要一堆变量来为游标供电。
One issue with your current code, as @automatic has mentioned, is that you're assuming INSERTED only holds one row. 正如@automatic提到的那样,当前代码的一个问题是,您假设INSERTED仅保存一行。 If it has more than one, then you'll throw an error when you try to assign a column to a variable.
如果它不止一个,那么当您尝试为变量分配列时会抛出错误。
For reasons of elegance, maintainability, and performance, I strongly urge you to abandon this cursor and run a simple insert (since that's all that your cursor is doing anyway). 出于优雅,可维护性和性能的原因,我强烈建议您放弃该游标,然后运行一个简单的插入操作(因为无论如何游标都可以这样做)。
Possible problem is here - 可能的问题在这里-
CREATE TRIGGER dbo.Posts_Raw_To_Queue_Trigger
ON SendNotificationPostsRaw
-- for view
INSTEAD OF INSERT
-- OR
-- for table
AFTER INSERT
AS BEGIN
DECLARE
@PostID UNIQUEIDENTIFIER
, @UserID UNIQUEIDENTIFIER
, @ProfID INT
, @Email NVARCHAR(100)
, @CreationTime DATETIME
, @SpecialityID INT
SELECT @ProfID = ProfessionalID
, @Email = Email
FROM Professionals
WHERE UserID = @UserID
-- this posible return invalid result (random record from inserted sequence)
SELECT @PostID = I.PostID
, @UserID = I.UserID
, @CreationTime = I.CreationTime
FROM INSERTED I
DECLARE post_relation_cursor CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
SELECT CategoryID
FROM dbo.PostCategoryRelations
WHERE PostId = @PostID;
OPEN post_relation_cursor;
FETCH NEXT FROM post_relation_cursor INTO @SpecialityID
WHILE @@FETCH_STATUS=0 BEGIN
INSERT INTO SendNotificationPostsQueue (
UserID
, PostID
, SpecialityID
, TemplateID
, CreationTime
, SendTime
, JSONParameters
)
SELECT
@UserID
, @PostID
, @SpecialityID --- !!!
, 1
, '04/11/2013'
, '04/11/2013'
, ''
FETCH NEXT FROM post_relation_cursor INTO @SpecialityID;
END;
CLOSE post_relation_cursor;
DEALLOCATE post_relation_cursor;
END
Update 更新
If I understand you correctly, the business logic must be like this: 如果我理解正确,则业务逻辑必须是这样的:
CREATE TRIGGER dbo.Posts_Raw_To_Queue_Trigger
ON dbo.SendNotificationPostsRaw
[INSTEAD OF]/[AFTER] INSERT
AS BEGIN
SET NOCOUNT ON;
DECLARE
@PostID UNIQUEIDENTIFIER
, @UserID UNIQUEIDENTIFIER
, @ProfID INT
, @Email NVARCHAR(100)
, @CreationTime DATETIME
, @SpecialityID INT
DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
SELECT
i.PostID
, i.UserID
, ProfID = p.ProfessionalID
, p.Email
, i.CreationTime
, pcr.CategoryID
FROM INSERTED i
JOIN dbo.Professionals p ON i.UserID = p.UserID
JOIN dbo.PostCategoryRelations pcr ON i.PostID = pcr.PostID
OPEN cur
FETCH NEXT FROM cur INTO
@PostID
, @UserID
, @ProfID
, @Email
, @CreationTime
, @SpecialityID
WHILE @@FETCH_STATUS = 0 BEGIN
INSERT INTO dbo.SendNotificationPostsQueue
(
UserID
, PostID
, SpecialityID
, TemplateID
, CreationTime
, SendTime
, JSONParameters
)
SELECT
@UserID
, @PostID
, @SpecialityID
, 1
, @CreationTime
, @CreationTime
, ''
FETCH NEXT FROM cur INTO
@PostID
, @UserID
, @ProfID
, @Email
, @CreationTime
, @SpecialityID
END
CLOSE cur
DEALLOCATE cur
END
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.