tags:

views:

37

answers:

2

I often write T-SQL loops that look like this in upgrade scripts:

While Exists (Select * From #MyTable)
    Begin
    Declare @ID int, @Word nvarchar(max)
    Select Top 1 @ID=ID, @Word=[Word] From #MyTable
    -- Do something --
    Delete #MyTable Where ID=@ID
    End

Works a treat but I noticed the new Delete Top function which would be useful when #MyTable is just a list of strings. In this case, would this work:

While Exists (Select * From #MyTable)
    Begin
    Declare @Word nvarchar(max)
    Select Top 1 @Word=[Word] From #MyTable
    -- Do something --
    Delete Top(1) #MyTable
    End

Well yes, it works in my test script but is this safe? Will Select Top 1 and Delete Top(1) always refer to the same record or is Top a little more vague.

Thanks, Rob.

+2  A: 

If you often write loops either you are doing something wrong or your database needs a redesign or you are inserting large batches of data that need to run in batches of 1000 records or so. I'll bet almost everything you are doing could be done in a set-based fashion and improve performance tremendously. I can't show you how without knowing what kind of thing happens inteh do somthing, but likely it can be made set-based by using a case startement.

HLGEM
+1, loops+database=slow. however, the OP is not using a cursor!
KM
And I never said he was. But there is a good chance that what he is doing can be done in a set-based fashion.
HLGEM
Sorry, I should have clarified "I often write loops in upgrade scripts"... would never do anything like that in the actual application itself!
Rob Nicholson
+3  A: 

No, your second example is not safe.

If you are going to use "SELECT TOP ..." (and you care about the order in which the rows are selected) you should really use an "ORDER BY" to explicitly specify the order. You MIGHT get the order you want without "ORDER BY", but SQL Server makes no guarantees about the order of returned rows when ORDER BY is not used.

In the case of "DELETE TOP ..", you can't add an "ORDER BY", so you should use a WHERE clause which uniquely identifies the row(s) to be deleted, as you have done in your first example.

Moe Sisko
Thank for this, I kind of suspected this was the case.
Rob Nicholson