2

パフォーマンスの問題に悩まされている場合、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
4

1 に答える 1

8

さて、あなたは構造化されたプログラマーのように考えてコーディングしています-プログラムフローを最も厳密に制御して、1つずつ直線的に。それが私たち(ほぼ)全員がプログラムするように考えられてきた方法です。

SQLの人のように考える必要があります-データのSETSで(単一の行ではなく、一度に1つずつ)。

アルゴリズムの各ステップを厳密に制御する必要はありません。代わりに、 SQL Serverに必要なものを伝えるだけで、各ステップの実行方法ではありません。

最後に、テーブルに一連の行を挿入しAuditLogます。なぜそのためのカーソルが必要なのですか?

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

これで完了です。テーブルに挿入したいものを定義します-SQLServerにそれを行う方法を非常に詳細に伝えないでください-それは非常によく知っています、ありがとう!

マーク

于 2009-08-26T04:59:27.693 に答える