В SQL Server есть способ избежать использования курсора? - PullRequest
4 голосов
/ 05 июля 2010

У меня есть таблица, в которой каждая запись имеет Table_Name (имя таблицы). Затем я использую Курсор, чтобы выбрать все имена таблиц, относящиеся к какой-либо записи в Курсоре. Затем я делаю WHILE для каждого имени таблицы в Курсоре, чтобы выполнить какую-то работу.

Я хочу знать, возможно ли решить эту проблему без использования курсора.

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

Имя каждой таблицы в курсоре. Я выполняю динамический SQL-запрос, например:

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

У меня такой вопрос: можно ли избежать использования курсора для решения этой проблемы?

К сожалению, дизайн наличия имени таблицы для ссылки на таблицу не может быть изменен, что я бы сделал немедленно, если бы мог.

Ответы [ 3 ]

1 голос
/ 05 июля 2010

Ну, вы можете скрыть использование курсора, используя (недокументированную, но широко используемую) хранимую процедуру MS sp_MSforeachdb (у Google есть много примеров); но он использует курсор внутри, так что если это философское возражение, то это не очень помогает.

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

1 голос
/ 05 июля 2010

да , вы можете решить эту проблему без использования курсора. Вместо этого вам нужно ввести новую таблицу, в которой хранится имя таблицы из фактической таблицы вместе с автоматически генерируемым столбцом идентификатора.

Проверьте приведенный ниже пример запроса

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' 

вместо вышеуказанного запроса, вы можете использовать свой запрос для заполнения табличной переменной

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

И

--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
1 голос
/ 05 июля 2010

Да, вы можете избежать курсора, но вы не можете избежать динамических запросов.

Возможно, вы могли бы сделать запрос, который возвращает все динамические запросы, объединенные в одну строку. Таким образом, вы могли бы выполнить их все без использования цикла, но это не лучше ...

Если вы не можете изменить дизайн базы данных, вы застряли с динамическими запросами.

...