views:

58

answers:

3

I have a table where each record has a Table_Name (name of a table). I then use a Cursor to select all table names related to some record in to a Cursor. Then I do a WHILE for each table name in the Cursor to do some job.

I want to know if it's possible to solve this problem without using a Cursor.

DECLARE tables_cursor CURSOR FAST_FORWARD FOR SELECT Table_Name FROM Some_Table WHERE ...

FETCH NEXT FROM tables_cursor INTO @Dynamic_Table_Name
WHILE @@FETCH_STATUS = 0
BEGIN
...
END

Foreach table name in the cursor I do a dynamic SQL query like this:

SELECT @sql = '
    UPDATE dbo.' + @Dynamic_Table_Name + '
    SET ...'
EXEC sp_executesql @sql, @params, ...

My question is this: Is it possible to avoid using Cursor to solve this problem?

Unfortunately the design of having table name to reference a table can't be changed, of which I would have done immediately if I could.

A: 

Yes, you could avoid the cursor, but you can't avoid the dynamic queries.

You could possibly make a query that returns all the dynamic queries concatenated together as a single string. That way you could execute them all without using a loop, but that's not really any better...

If you can't change the database design, you are stuck with dynamic queries.

Guffa
So if the query returns 3 table names, then I would concatenate them together such as: 'Table_1 Table_2 Table_3' where I could split the string up by space to know each table name? Would this solution be any faster than using a Cursor?And lastly, can you show an example?
Jón Trausti
@Jón: No, you can't update multiple tables at once. You would have to concatenate the complete queries: `update sometable ...;update othertable ....;update moretable ...`. You will still have to do each update, so the difference from using a cursor would be marginal.
Guffa
A: 

Well, you can hide the use of a cursor by using the (undocumented, but widely-used) MS stored procedure sp_MSforeachdb (Google has lots of examples); but that uses a cursor internally, so if it's a philosophical objection then that doesn't really help.

I don't think there can be a set-based way to do this kind of thing, since each table probably has a different relational structure.

AakashM
A: 

yes, you can solve this problem without using cursor. Instead you need to introduce the new table which stores the table name from actual table along with auto generated id column.

Check out the below sample query

declare @test table (id  int identity,tableName varchar(20))

insert into @test 
            select 'abc' union all
            select '123' union all
            select '345' union all
            select 'sdf' union all
            select 'uhyi' 

instead above query, you can use your query to populate the table variable

insert into @test 
  SELECT Table_Name FROM Some_Table WHERE ...   

And

--select * from @test

declare @cnt int
declare @incr int
select @cnt = count(id) from @test
set @incr = 1
while (@incr <= @cnt)
begin
    select tableName from @test where id = @incr
    set @incr =@incr + 1
end

Cheers

Ramesh Vel
Thank you for the response, would you consider this method faster than using a cursor?
Jón Trausti
Sure, because cursor blocks the table when looping through... its avoided here... maybe you could run a profiler yourself to check both queries performance....
Ramesh Vel
Thank you for the good answer to my problem.
Jón Trausti