2009-08-26 84 views
2

如果我遇到性能问题,那么在SQL中使用游标的最佳选择是什么?避免使用SQL中的游标

我得到了下面的代码,其中它使用光标循环和插入记录。通过一个线性,一个在程序流程tighest控制 -

 DECLARE @AuditBatchID_logRow INT, 
    @AuditOperationID_logRow INT, 
    @RowIdentifier_logRow nvarchar(200), 
    @AuditDBTableID_logRow INT, 
    @AuditLogRowID INT, 

    @AuditDBColumnID INT, 
    @NewValue nvarchar(200), 
    @PreviousVaue nvarchar(200), 
    @NewDisplayValue nvarchar(200) 

    DECLARE Crsr_AUDITLOGROW CURSOR LOCAL FORWARD_ONLY STATIC 
     FOR 
     SELECT [t0].[AuditBatchID], 
       [t1].[AuditOperationID], 
       [t1].[RowIdentifier], 
       [t0].[AuditTableID], 
       [t1].[AuditLogRowID] 
     FROM [AuditBatchTable] AS [t0] 
     INNER JOIN [AuditLogRow] AS [t1] 
       ON [t0].[AuditBatchTableID] = [t1].[AuditBatchTableID] 

    Open Crsr_AUDITLOGROW 

    FETCH NEXT FROM Crsr_AUDITLOGROW 
    INTO @AuditBatchID_logRow, 
      @AuditOperationID_logRow, 
      @RowIdentifier_logRow, 
      @AuditDBTableID_logRow, 
      @AuditLogRowID 

    While(@@FETCH_STATUS = 0) 
    BEGIN 
     INSERT INTO AuditLog(AuditLogRowID, AuditColumnID, 
          NewValue, OldDisplayValue, NewDisplayValue) 
     (SELECT @AuditLogRowID, 
       [ac].[AuditColumnID], 
       [t0].[UserEnteredValue], 
       [t0].[PreviousDisplayValue], 
       [t0].[DisplayValue] 
      FROM FMG_PROD.dbo.AuditLog AS [t0] 
      INNER JOIN FMG_PROD.dbo.AuditDBColumn AS [t1] 
      ON [t0].[AuditDBColumnID] = [t1].[AuditDBColumnID] 
      INNER JOIN FMG_PROD.dbo.AuditDBTable AS [t2] 
      ON [t1].[AuditDBTableID] = [t2].[AuditDBTableID] 
      INNER JOIN AuditTable AS [AT] 
      ON [t2].AuditDBTable = [AT].AuditTable 
      INNER JOIN AuditColumn AS [AC] 
      ON [AT].AuditTableID = [AC].AuditTableID 
      WHERE  
      ([t0].[AuditBatchID] = @AuditBatchID_logRow) 
      AND ([t0].[AuditOperationID] = @AuditOperationID_logRow) 
      AND ([AT].[AuditTableID] = @AuditDBTableID_logRow) 
      AND [AC].AuditColumn = [t1].AuditDBColumn 
      AND (@RowIdentifier_logRow = 
       CASE ISNUMERIC(@RowIdentifier_logRow) 
        WHEN 1 then 
         CAST ([t0].[RowID] AS VARCHAR(200)) 
        ELSE 
         CAST([t0].[RowGUID] AS VARCHAR(200)) 
    END)) 

     FETCH NEXT FROM Crsr_AUDITLOGROW 
      INTO @AuditBatchID_logRow, 
       @AuditOperationID_logRow, 
       @RowIdentifier_logRow, 
       @AuditDBTableID_logRow, 
       @AuditLogRowID 
END 

CLOSE Crsr_AUDITLOGROW 
DEALLOCATE Crsr_AUDITLOGROW 

回答

8

好吧,你想和编码就像一个结构化编程。这就是我们(几乎)所有人都被认为要编程的方式。

你需要像一个SQL家伙一样思考 - 在SETS数据(不是单行,一次一个)。

避免需要严格控制算法的每一步 - 相反,只是告诉SQL服务器什么你想要的 - 不如何做的每一步!

最后,您将一堆行插入到AuditLog表中。为什么你需要一个游标呢?

INSERT INTO AuditLog(...list of columns.....) 
    SELECT (....list of columns....) 
    FROM Table1 
    INNER JOIN .......... 
    INNER JOIN ......... 
    WHERE ........ 

你就完成了!定义什么你想要插入表 - 不要告诉SQL Server在详细说明如何做 - 它会知道很好,谢谢!

Marc

+1

+1对于集合思维的重要性。 – APC 2009-08-26 06:11:53

+0

谢谢马克,它帮了我很多。减少大量代码并获得更好的性能。 – Sreedhar 2009-08-26 06:31:52

+0

太棒了!很高兴我能帮上忙! – 2009-08-26 07:07:27