2013-04-11 25 views
0

我在触发器中创建了一个光标,它不能正常工作。请帮我解决它SQL Server触发器的光标不起作用

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 [email protected] 
SELECT @PostID = I.PostID,@UserID = I.UserID ,@CreationTime =I.CreationTime FROM INSERTED I 

DECLARE post_relation_cursor CURSOR FOR select CategoryId from PostCategoryRelations where [email protected]; 

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 

如果我删除光标并插入虚拟值到SendNotificationPostsQueue,它的工作原理。所以我的光标有问题...请告诉我光标为什么不起作用?

+0

你是什么现在我的意思是如果你使用光标会发生什么。它给了什么结果 – 2013-04-11 12:17:35

+1

看起来你在插入表中只有一行。这是错误的。不知道这是不是你的“不工作”的原因,但在任何情况下都是错误的。 – automatic 2013-04-11 12:19:04

+0

我正在使用Sql Server Web Admin,所以我看不到任何错误。我无法调试 – 2013-04-11 12:19:25

回答

3

一点也没有”看起来你需要使用光标,而不是更好几乎在所有情况下都使用一个。怎么我不使用的插件,该插件只能插入一行的values条款

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 

注:与标准的刀片只需更换您的触发器的主体(开始和结束之间的部分)。我将select语句作为insert的一部分,从而插入与select返回一样多的行。这意味着我们不需要使用游标,也不需要一堆变量来为游标提供动力。

@automatic提到的一个问题就是你假设INSERTED只保存一行。如果它有多个,那么当你尝试将一个列分配给一个变量时,你会发出一个错误。由于优雅,可维护性和性能的原因,我强烈建议你放弃这个游标并运行一个简单的插入(因为这就是你的光标所做的一切)。

+0

好吧,我必须循环整个表,我需要一个光标 – 2013-04-11 12:47:05

+0

我们可以打赌吗? SQL和RDBMS系统处理数据集。很少需要一次处理一行。我的触发器中没有看到任何暗示这是其中的一种情况。 – 2013-04-11 12:47:49

+0

好吧,我的问题是我有时必须插入3行,如果该职位有3个SpecialityID – 2013-04-11 12:55:39

1

可能的问题是在这里 -

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 

更新

如果我理解正确的话,业务逻辑必须是这样的:

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 
+0

我看不出有什么不同。你会告诉我这个问题吗?感谢你的时间我的朋友。 – 2013-04-11 12:40:48

+0

并且它给出这个错误'AFTER'附近的语法不正确。 – 2013-04-11 12:43:08

+0

的逻辑是正确的,但它没有做insert.I刚检查... – 2013-04-11 12:54:14