SQL触发器 - 使用基于集合的操作转换游标

时间:2011-10-27 03:13:16

标签: sql triggers cursor

我试图了解基于集合的操作的基础知识。我已经读取基于集合的操作在性能方面远远好于在游标中循环。我可以采取哪些步骤将游标转换为设置操作?以下是我正在使用的几个例子

CREATE Trigger DataUpdate ON [Data]
    FOR UPDATE
    AS
      SET NOCOUNT ON
    BEGIN
       declare @Id int
       declare cur cursor for select DataId from Deleted
       open cur
       fetch next from c into @Id
       while @@FETCH_STATUS = 0
          begin
            if 
               UPDATE(ID) and
               UPDATE(Title) or
               UPDATE(Description)             
             BEGIN
                update Data 
                set ModDate = getdate()
                where ID = @Id
             END
            fetch next from c into @Id
          end
       close cur
       deallocate cur
    end

另一个触发器

CREATE  TRIGGER DataAudit
      ON [Data] FOR UPDATE
      AS

      SET NOCOUNT ON

    IF UPDATE(ModDate)
         BEGIN
           SET NOCOUNT ON
           DECLARE @ParentId INT
           DECLARE @ChildId INT
           DECLARE @Export BIT

           DECLARE cursorInserted CURSOR FOR
              select ParentID, ChildID, Export from INSERTED

           OPEN  cursorInserted 

           Fetch next from cursorInserted into @ParentId, @ChildId, @Export

           WHILE @@FETCH_STATUS = 0
           BEGIN             
               DECLARE @brief BIT

               DECLARE cursorBriefcase CURSOR FOR
                select ShowExport
                  from Sites 
              where SiteID in (select ds.siteid from DataSiteIDs as ds where ChildID = @ChildId)   

               OPEN cursorBriefcase
                 -- Perform the first fetch.
                 FETCH NEXT FROM cursorBriefcase INTO @brief

                 -- Check @@FETCH_STATUS to see if there are any more rows to fetch.
                 WHILE @@FETCH_STATUS = 0 and @brief = 0
                   BEGIN
                      FETCH NEXT FROM cursorBriefcase INTO @brief
                   END
                 CLOSE cursorBriefcase
                 DEALLOCATE cursorBriefcase

             IF @brief = 0 and 
                @Export = 1   and 
                ((SELECT Distinct ParentID FROM Sites Where ParentID = @ParentId AND (TemplateID = 5 OR TemplateParams = 1) ) > 0) and 
                ((Select Distinct ParentID From SubUserGroupIDs Where ParentID = @ParentId) > 0)
             BEGIN
                -- Populate the SubAuditItems table with rows on hold
                INSERT INTO SubAuditItems (ChildID, ParentID, RecordDate, Type, FromTable)
                VALUES (@ChildId, @ParentId,  GETDATE(), 'MOD', 'Data')
             END

           Fetch next from cursorInserted into @ParentId, @ChildId, @Export
           END
           CLOSE cursorInserted
           DEALLOCATE cursorInserted    

        END

2 个答案:

答案 0 :(得分:0)

@Yusuf:你能告诉我们一些细节吗?你想要实现什么?如果你想保持从表中删除的记录,你可以这样做:

CREATETRIGGER [dbo].[UpdateCustomerHistory]
    ON [dbo].[tblCustomers]
AFTER DELETE
AS 

---------------------------------------------------
-- Insert the deleted Record in History
---------------------------------------------------
INSERT INTO tblCustomersHistory
(
    CustomerId, Name, DateCreated
)
------ Get deleted row
SELECT  CustomerId, Name, GETDATE()
FROM    DELETED

答案 1 :(得分:0)

这应该适用于第一个触发器的主体:

UPDATE d                 
 SET ModDate = getdate()
 FROM inserted i
 JOIN data d ON i.id = d.ID
 JOIN deleted del ON i.id = del.id
 WHERE 
   (i.Id <> del.id)
 OR
   (i.title <> del.title)
 OR
   (i.description <> del.description)

如果我正确解释了你的第二个例子,那么触发器的主体就像是:

 INSERT INTO SubAuditItems (ChildID, ParentID, RecordDate, Type, FromTable)  
 SELECT i.ChildID,i.ParentID, GETDATE(), 'MOD', 'Data' 
 FROM INSERTED 
 JOIN DataSiteIDs s ON ds.childid = i.childid
 JOIN Sites s ON ds.siteid = s.siteid
 WHERE i.Export = 1