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

发布于 2024-12-12 06:40:00 字数 2795 浏览 0 评论 0原文

我试图了解基于集合的操作的基础知识。我读过基于集合的操作在性能上比游标循环要好得多。我需要采取哪些步骤将游标转换为设置操作?这是我正在使用的几个例子

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

I am trying to understand the basics of set based operation. I have read set based operation is far better in performance than looping in cursor. What steps do I take to convert cursors to set operations? Here are couple examples I am working with

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

And another trigger

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅忆 2024-12-19 06:40:02

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

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 

This should do for the body of the first trigger:

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)

If I have correctly interpreted your second example, the body of the trigger would be something like:

 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 
故人爱我别走 2024-12-19 06:40:01

@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

@Yusuf: Can you please give us a little more detail? what you want to achieve? if you want to maintain the records deleted from a table you can do it like:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文