2009-08-26 88 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