Избегание курсора в SQL - PullRequest
       10

Избегание курсора в SQL

2 голосов
/ 26 августа 2009

Какова лучшая альтернатива использованию курсора в SQL, если у меня проблемы с производительностью?

Я получил следующий код, в котором он использует курсор для циклического просмотра и вставки записей.

      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

1 Ответ

8 голосов
/ 26 августа 2009

Ну, вы думаете и кодируете, как структурированный программист - линейно, один за другим, в жестком контроле за ходом программы. Вот как мы (почти) все думали программировать.

Вам нужно думать как SQL-парень - в SETS данных (не в одной строке, по одной за раз).

Избегайте необходимости жестко контролировать каждый шаг алгоритма - вместо этого просто скажите SQL Server ЧТО вы хотите - не КАК для выполнения каждого шага!

В конце вы вставляете группу строк в таблицу AuditLog. Зачем вам курсор для этого ??

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

и все готово! Определите что вы хотите вставить в таблицу - НЕ подробно сообщайте SQL Server, как это сделать - он будет очень хорошо знать, спасибо!

Марк

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...