Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Курсор в курсоре  [new]
VladislavVV
Member

Откуда:
Сообщений: 994
Всем добрый день

Кто нибуть работал с курсором в курсоре?
Работает ли?
Есть ли подводные камни?

Спасибо за ответы.

MS SQL 2000
14 мар 06, 11:21    [2445298]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74901
Я работал.
Работает.
Есть.
14 мар 06, 11:28    [2445358]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
Crimean
Member

Откуда:
Сообщений: 13144
а что, сложно сделать cross join и один курсор ? :)
14 мар 06, 11:30    [2445380]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7370

BOL - Declare cursor - Examples: B. Use nested cursors to produce report output


Posted via ActualForum NNTP Server 1.3

14 мар 06, 11:37    [2445443]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
VladislavVV
Member

Откуда:
Сообщений: 994
pkarklin
Я работал.
Работает.
Есть.


какие-если не секрет?
14 мар 06, 11:39    [2445466]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
VladislavVV
Member

Откуда:
Сообщений: 994
Crimean
а что, сложно сделать cross join и один курсор ? :)


там хитрая идея-просто так не получится
просто если есть глюки в курсор в курсоре- то прийдется обойтись
другм, более тормознутым но 100% действ рез-том
14 мар 06, 11:42    [2445489]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74901
Обычно до этого абзаца статьи раздела DECLARE CURSOR не дочитывают:

автор
Variables may be used as part of the select_statement that declares a cursor. Cursor variable values do not change after a cursor is declared. In SQL Server version 6.5 and earlier, variable values are refreshed every time a cursor is reopened.


Т.е. вложенный курсор нужно бязательно декларировать внутри внешнеого.
14 мар 06, 11:43    [2445502]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
VladislavVV
Member

Откуда:
Сообщений: 994
pkarklin
Обычно до этого абзаца статьи раздела DECLARE CURSOR не дочитывают:

автор
Variables may be used as part of the select_statement that declares a cursor. Cursor variable values do not change after a cursor is declared. In SQL Server version 6.5 and earlier, variable values are refreshed every time a cursor is reopened.


Т.е. вложенный курсор нужно бязательно декларировать внутри внешнеого.


т.е. как в примере

обьявили К1
фетч к1
...
обьявили К2
фетч к2

...

закрыли К2
закрыли К1


других камней нет?
14 мар 06, 11:47    [2445526]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Курсор в курсоре  [new]
TheKLF
Member

Откуда:
Сообщений: 22
простите, что поднимаю "мертвую" тему, но можно ли пример кода "курсор в курсоре"

допустим такого вида: есть таблица с некими значениями(таблица 1), которые будем использовать для конструкции запроса и есть таблица с элементами(таблица 2), которые надо проверить на наличие в общей БД

SELECT * FROM 'параметр из таблицы 1' WHERE [field] like 'параметр из таблицы 2'
14 мар 19, 18:01    [21832898]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6025
TheKLF,

вложенные курсоры прям в документации описаны

B. Using nested cursors
https://docs.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-2017
14 мар 19, 18:07    [21832907]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
aleks222
Member

Откуда:
Сообщений: 495
TaPaK
TheKLF,

вложенные курсоры прям в документации описаны

B. Using nested cursors
https://docs.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-2017


Прочитал три раза. А что там "вложенного" то?
Так можно и десять курсоров "вложить".
14 мар 19, 19:03    [21832959]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
SIMPLicity_
Member

Откуда: (((@)))
Сообщений: 8502
aleks222
TaPaK
TheKLF,

вложенные курсоры прям в документации описаны

B. Using nested cursors
https://docs.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-2017


Прочитал три раза. А что там "вложенного" то?
Так можно и десять курсоров "вложить".


Экзампл Би: B. Using nested cursors to produce report output

Или это был "САРКАЗМ"
14 мар 19, 19:55    [21832992]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
TheKLF
Member

Откуда:
Сообщений: 22
Спасибо большое за ответы!

вот мой способ решения задачи "Курсор в Курсоре"

+
--проверяем наличие первой временной таблицы, если она существует - то удаляем её
if OBJECT_ID('tempdb..#TempTable') is not null
begin
	drop table #TempTable
end
--проверяем наличие второй временной таблицы, если она существует - то удаляем её
if OBJECT_ID('tempdb..#TempTableCodes') is not null
begin
	drop table #TempTableCodes
end

select [name] 
INTO #TempTable
FROM sys.objects WHERE type in (N'U') and [name] LIKE 'StoreRetail_number_%' ORDER BY [name]
print 'сколько нашли магазинов'

--создаём таблицу для данных, которые мы загрузим из файла
create table #TempTableCodes
(
[name] nvarchar(30)
)
--из внешнего файла загружаем значения для обработки
bulk insert #TempTableCodes
	from 'd:\codes_search.txt'
	with (ROWTERMINATOR = '\n')

print 'контроль работы'

select * from #TempTableCodes
print ' #TempTableCodes'
select * from #TempTable
print ' #TempTable'
print ' '
print ' '

declare @code nvarchar(30)
declare @table nvarchar (50)
declare @mySel nvarchar (500)

--объявляем первый курсор
declare @CursorTables CURSOR
--заполняем его значениями временной таблицы
set @CursorTables = CURSOR for
	select * from #TempTable
open @CursorTables

	fetch next from @CursorTables into @table
	while @@FETCH_STATUS = 0
	begin
			print ' Блок - @CursorTables'
                                --объявляем второй курсор
				declare @CursorCodeTables CURSOR
                                --заполняем его из нужной ему временной таблицы
				set @CursorCodeTables = CURSOR local for
				select * from #TempTableCodes
				open @CursorCodeTables

					fetch next from @CursorCodeTables into @code
					while @@FETCH_STATUS = 0
						begin
							--формируем запрос к БД
							set @mySel = 'SELECT [Store],[Product],[Item],[Seller],[Orders] FROM ' +@table+ ' WHERE [Orders] like ''%' + @code + '%'''
							print 'контроль как выглядит мой запрос=  '+@mySel
                                                        --выполняем запрос к БД
							EXEC sp_executesql @mySel
							fetch next from @CursorCodeTables into @code
			                        end
                     fetch next from @CursorTables into @table
	end

	close @CursorCodeTables
	deallocate @CursorCodeTables

	close @CursorTables
	deallocate @CursorTables
14 мар 19, 20:56    [21833045]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
SIMPLicity_
Member

Откуда: (((@)))
Сообщений: 8502
TheKLF
Спасибо большое за ответы!

вот мой способ решения задачи "Курсор в Курсоре"

+
--проверяем наличие первой временной таблицы, если она существует - то удаляем её
if OBJECT_ID('tempdb..#TempTable') is not null
begin
	drop table #TempTable
end
--проверяем наличие второй временной таблицы, если она существует - то удаляем её
if OBJECT_ID('tempdb..#TempTableCodes') is not null
begin
	drop table #TempTableCodes
end

select [name] 
INTO #TempTable
FROM sys.objects WHERE type in (N'U') and [name] LIKE 'StoreRetail_number_%' ORDER BY [name]
print 'сколько нашли магазинов'

--создаём таблицу для данных, которые мы загрузим из файла
create table #TempTableCodes
(
[name] nvarchar(30)
)
--из внешнего файла загружаем значения для обработки
bulk insert #TempTableCodes
	from 'd:\codes_search.txt'
	with (ROWTERMINATOR = '\n')

print 'контроль работы'

select * from #TempTableCodes
print ' #TempTableCodes'
select * from #TempTable
print ' #TempTable'
print ' '
print ' '

declare @code nvarchar(30)
declare @table nvarchar (50)
declare @mySel nvarchar (500)

--объявляем первый курсор
declare @CursorTables CURSOR
--заполняем его значениями временной таблицы
set @CursorTables = CURSOR for
	select * from #TempTable
open @CursorTables

	fetch next from @CursorTables into @table
	while @@FETCH_STATUS = 0
	begin
			print ' Блок - @CursorTables'
                                --объявляем второй курсор
				declare @CursorCodeTables CURSOR
                                --заполняем его из нужной ему временной таблицы
				set @CursorCodeTables = CURSOR local for
				select * from #TempTableCodes
				open @CursorCodeTables

					fetch next from @CursorCodeTables into @code
					while @@FETCH_STATUS = 0
						begin
							--формируем запрос к БД
							set @mySel = 'SELECT [Store],[Product],[Item],[Seller],[Orders] FROM ' +@table+ ' WHERE [Orders] like ''%' + @code + '%'''
							print 'контроль как выглядит мой запрос=  '+@mySel
                                                        --выполняем запрос к БД
							EXEC sp_executesql @mySel
							fetch next from @CursorCodeTables into @code
			                        end
                     fetch next from @CursorTables into @table
	end

	close @CursorCodeTables
	deallocate @CursorCodeTables

	close @CursorTables
	deallocate @CursorTables


Студия ошибок не дала (запускать не стал, только смотрел анализ кода), но мне почему-то кажется, что вот это

	close @CursorCodeTables
	deallocate @CursorCodeTables


должно стоять непосредственно перед

fetch next from @CursorTables into @table
14 мар 19, 23:37    [21833121]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6272
Как-то модно стало объявлять declare @CursorTables CURSOR. Или это из одной бочки решения копипастом.
Это лишь бы LOCAL не написать, что ли? Или для крутости все переменные согнать в начало процедуры?
Ошибка появится во время выполнения при повторном открытии курсора.
15 мар 19, 00:11    [21833129]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
TheKLF
Member

Откуда:
Сообщений: 22
Владислав Колосов,

спасибо за ответ!

А можно чуть подробнее объяснить ваш ответ.
Это не copy-paste, просто на всех форумах одно и тоже написано.
15 мар 19, 10:23    [21833374]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
invm
Member

Откуда: Москва
Сообщений: 8441
TheKLF,

Курсоры тут нафиг не нужны:
if OBJECT_ID('tempdb..#TempTableCodes') is not null
begin
	drop table #TempTableCodes
end;

create table #TempTableCodes
(
[name] nvarchar(30)
);

--из внешнего файла загружаем значения для обработки
bulk insert #TempTableCodes
	from 'd:\codes_search.txt'
	with (ROWTERMINATOR = '\n');

declare @sql nvarchar(max);

select
 @sql = t.x.value('.', 'nvarchar(max)')
from
 (
  select
   N'SELECT a.[Store],a.[Product],a.[Item],a.[Seller],a.[Orders] FROM ' + quotename(schema_name(schema_id))) + N'.' + quotename(name) +
   N' a WHERE exist(select * from #TempTableCodes b where a.[Orders] like ''%'' + b.name + ''%'');'
  FROM sys.objects WHERE type in (N'U') and [name] LIKE 'StoreRetail_number_%' ORDER BY [name]
  for xml path('')
 ) t(x);

exec sp_executesql @sql;


В дальнейшем возможно осознаете, что подход "для каждого магазина - своя таблица" также ущербен.
15 мар 19, 11:02    [21833415]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 27938
TheKLF
А можно чуть подробнее объяснить
Вариант с переменной
declare @CursorTables CURSOR
set @CursorTables = CURSOR for
	select * from #TempTable
Эквивалентен варианту
declare CursorTables CURSOR LOCAL 
	select * from #TempTable

Но в первом варианте можно разнести declare и set снаружи и внутри цикла, и тогда получится ошибка.
15 мар 19, 11:05    [21833419]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
court
Member

Откуда:
Сообщений: 1626
alexeyvg
Вариант с переменной
declare @CursorTables CURSOR
set @CursorTables = CURSOR for
	select * from #TempTable

Эквивалентен варианту
declare CursorTables CURSOR LOCAL 
	select * from #TempTable


Они эквивалентны, если свойство CURSOR_DEFAULT БД = LOCAL

... а оно, имхо, по умолчанию - GLOBAL
15 мар 19, 11:24    [21833456]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 27938
court
Они эквивалентны, если свойство CURSOR_DEFAULT БД = LOCAL
А, точно
BOL
The syntax rules for SET @cursor_variable do not include the LOCAL and GLOBAL keywords. When the SET @cursor_variable = CURSOR... syntax is used, the cursor is created as GLOBAL or LOCAL, depending on the setting of the default to local cursor database option.
Я то думал, с переменной он всегда получается LOCAL (никогда не использовал курсорные переменные)

Значит, вообще так нельзя писать, ибо непонятно, что получишь.
15 мар 19, 11:32    [21833472]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6272
court,

тип курсора по умолчанию определён в свойствах базы данных. Можно указать явно при создании базы или свойство копируется из базы model.
15 мар 19, 14:20    [21833859]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
TheKLF
Member

Откуда:
Сообщений: 22
invm,

Спасибо большое!!! А не будет вам в большую тягость чуть расшифровать ваш код. Как оно работает



declare @sql nvarchar(max);

select
 @sql = t.x.value('.', 'nvarchar(max)')
from
 (
  select
   N'SELECT a.[Store],a.[Product],a.[Item],a.[Seller],a.[Orders] FROM ' + quotename(schema_name(schema_id))) + N'.' + quotename(name) +
   N' a WHERE exist(select * from #TempTableCodes b where a.[Orders] like ''%'' + b.name + ''%'');'
  FROM sys.objects WHERE type in (N'U') and [name] LIKE 'StoreRetail_number_%' ORDER BY [name]
  for xml path('')
 ) t(x);
вчера, 17:27    [21843003]     Ответить | Цитировать Сообщить модератору
 Re: Курсор в курсоре  [new]
iap
Member

Откуда: Москва
Сообщений: 46635
Надо ещё обратить внимание, что курсор по умолчанию ДИНАМИЧЕСКИЙ!
Так что будьте осторожны!
Все изменения в таблицах, на которых построен курсор, моментально отражаются в курсоре!
Например, если имеется ORDER BY, то изменённая запись может снова оказаться впереди
текущей позиции курсора и обработаться ещё раз. Вплоть до бесконечного цикла.
Обычно эту причину зацикливания не так-то просто найти.
вчера, 17:40    [21843018]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить