0

トリガー内にカーソルを作成しましたが、正しく動作しません。修正を手伝ってください

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

カーソルを削除してにダミー値を挿入するとSendNotificationPostsQueue、機能します。カーソルに問題があります...カーソルが機能しない理由を教えてください。

4

2 に答える 2

3

カーソルを使用する必要はまったくないようです。ほとんどの場合、カーソルを使用しない方がよいでしょう。トリガーの本体 (begin と end の間の部分) を標準の挿入に置き換えるだけです。

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

values1行しか挿入できない挿入句を使用していないことに注意してください。挿入の一部として選択ステートメントを配置しているため、選択が返すのと同じ数の行が挿入されます。これは、カーソルを使用する必要がなく、カーソルを動かすための変数の束を必要としないことを意味します。

@automatic が述べたように、現在のコードの 1 つの問題は、INSERTED が 1 行しか保持していないと想定していることです。複数ある場合、列を変数に割り当てようとするとエラーがスローされます。

優雅さ、保守性、およびパフォーマンスの理由から、このカーソルを放棄して単純な挿入を実行することを強くお勧めします (カーソルが実行しているのはそれだけだからです)。

于 2013-04-11T12:45:24.180 に答える
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
于 2013-04-11T12:31:22.960 に答える