2013-04-11 3 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

что вы теперь имеете в виду, что произойдет, если вы используете курсор. какой результат он дает –

+1

Похоже, вы предполагаете там только одну строку во вставленной таблице. Это не верно. Не знаю, является ли это причиной вашего «нерабочего», но в любом случае это неверно. – automatic

+0

Я использую Sql Server Web Admin, поэтому я не вижу никаких ошибок. Я не могу отлаживать –

ответ

3

Это Безразлично» t кажется, что вам нужно использовать курсор на всех, и было бы лучше не используя один почти во всех случаях. Просто замените корпус вашего триггера (часть между начала и конца) со стандартной вставки:

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 

Обратите внимание, как я не использую в положение режущей пластины, которая может только вставить одну строку values. Я помещаю оператор select как часть вставки, таким образом, вставляя столько строк, сколько возвращает select. Это означает, что нам не нужно использовать курсор, и вам не нужна куча переменных для включения курсора.

Одна проблема с вашим текущим кодом, как упомянуто в @automatic, заключается в том, что вы предполагаете, что INSERTED содержит только одну строку. Если он имеет более одного, то вы будете бросать ошибку при попытке присвоить столбец переменной.

Из-за элегантности, ремонтопригодности и производительности я настоятельно рекомендую вам отказаться от этого курсора и запустить простую вставку (так как это все, что делает ваш курсор в любом случае).

+0

ну, мне нужно петлю целую таблицу, мне нужно иметь курсор –

+0

Можем ли мы поспорить на это? Системы SQL и RDBMS работают с наборами данных. Очень редко приходится обрабатывать строки по одному. Я ничего не вижу в вашем триггере, который предполагает, что это один из тех случаев. –

+0

хорошо, моя проблема в том, что мне иногда приходится вставлять 3 строки, если сообщение имеет 3 SpecialityID –

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 

Update

Если я вас правильно понимаю, бизнес-логика должна быть такой:

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

Я не мог видеть разницу. не могли бы вы рассказать мне о проблеме. спасибо за ваше время, мой друг. –

+0

, а также Он дает эту ошибку. Неправильный синтаксис рядом с «ПОСЛЕ». –

+0

логика правильная, но она не делает insert.I только что проверила ... –

Смежные вопросы