views:

321

answers:

3

Hi guys:

We want to remove tons of obsolete data in a table, but this will lock table for a long while. Is is possible to use Cursor to delete, says, one hundred records per transaction in a while-loop ?

And where can I refer to the example?

+1  A: 

You can commit every 100 (or 1000, or whatever) records in the loop, releasing the lock and letting any pending operations get their work in. Otherwise you're generating a huge transaction log which eats greater than O(n^2) time when it gets large. This thing will be a large portion of the actual time spent, instead of getting the actual deleting done. If you batch and commit, you're safer, rollback/log files won't grow like crazy, and locks are manageable.

If however you need that huge rollback as an option, there's 2 choices:

  • Wait a long while
  • Backup the table first and then do the batch deletes
Nick Craver
+2  A: 

Something like this:

DECLARE @stillgoing bit;
SET @stillgoing = 1;

WHILE @stillgoing = 1
BEGIN
  DELETE TOP (100) YourTableName
  WHERE IsObsolete = 1;

  IF @@ROWCOUNT = 0
      SET @stillgoing = 0;

  CHECKPOINT /* Will encourage the log to clear if it's in Simple recovery model */
END

Edit: This will only work in SQL 2005 and on. As we've just learned it's SQL 2000, this code instead:

DECLARE @stillgoing bit
SET @stillgoing = 1

SET ROWCOUNT 100

WHILE @stillgoing = 1
BEGIN
  DELETE YourTableName
  WHERE IsObsolete = 1

  IF @@ROWCOUNT = 0
      SET @stillgoing = 0

  CHECKPOINT /* Will encourage the log to clear if it's in Simple recovery model */
END

And... Simple Recovery Model means that the log will truncate on checkpoints, rather than only when the log is backed up.

Rob Farley
hi, what do u mean by Simple Recovery Model.
Ricky
hi It seems not working in SQL 2000
Ricky
Hi, still not work; here is my query: DELETE TOP 100 XYZ WHERE DateCreated <= '2001/2/31'
Ricky
Sorry - my comment about SQL 2000 was wrong. TOP wasn't supported then. Try putting this at the start, and removing the "TOP 100". `SET ROWCOUNT 100`
Rob Farley
It means that the query will affect only 100 rows at a time.
Rob Farley
+1  A: 
Declare MyPrimaryKey [SomeType]

Declare @MyCursor Cursor For 

Select MyPrimayKey from MyTable

Open @MyCursor

Fetch Next From @MyCursor

Into
  @MyPrimaryKey

WHILE @@FETCH_STATUS = 0

BEGIN
   WaitFor Delay '00:00:05'

   Begin Transaction

   DELETE From MyTable where MyPrimaryKey = @MyPrimaryKey

   Commit Transaction

   Fetch Next From @MyCursor

   Into
     @MyPrimaryKey
END
John Hartsock
If you post code like this T-SQL snippet, please highlight those lines and use the "code" button (101 010) on the editor toolbar, or press Ctrl-K on your keyboard, to properly format that section as code so it can be display and syntax-highlighted nicely
marc_s
What's the intent for WaitFor Delay?
Ricky
the wait for delay is to pause and allow other transactions for the table to begin.
John Hartsock
Thank you. Your answer broden my eyes.
Ricky