SQL - Хранимая процедура Вызова для каждой записи

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

SELECT @SomeIds = (
    SELECT spro.Id 
    FROM SomeTable as spro
    INNER JOIN [Address] addr ON addr.Id = spro.Id 
    INNER JOIN City cty ON cty.CityId = addr.CityId
    WHERE cty.CityId = @CityId
)


WHILE @SomeIds  IS NOT NULL
BEGIN
    EXEC UpdateComputedFullText @SomeIds
END

Такая вещь выше не работает, конечно, но является там способом сделать что-то как этот?

46
задан Joe Phillips 18 January 2010 в 02:47
поделиться

7 ответов

Необходимо использовать курсор: Примеры курсора SQL Server

DECLARE @id int
DECLARE cursor_sample CURSOR FOR  
SELECT spro.Id 
FROM SomeTable as spro
    INNER JOIN [Address] addr ON addr.Id = spro.Id 
    INNER JOIN City cty ON cty.CityId = addr.CityId
WHERE cty.CityId = @CityId

OPEN cursor_sample
FETCH NEXT FROM cursor_sample INTO @id 
WHILE @@FETCH_STATUS = 0   
BEGIN  
    EXEC UpdateComputedFullText @id
    FETCH NEXT FROM cursor_sample INTO @id
END   

CLOSE cursor_sample
DEALLOCATE cursor_sample
-121--1125801-

Для одного из них знание языка C помогает понять, как работает память в ОС и на других языках высокого уровня. Когда всплывающие подсказки программы C # или Java используются в памяти, понимание того, что ссылки (которые в основном являются только указателями) также занимают память, и понимание того, сколько структур данных реализовано (которые вы получаете от создания собственного в C), помогает вам понять, что ваш словарь резервирует огромные объемы памяти, которые на самом деле не используются.

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

Я думаю, что C также помог мне понять сетевые протоколы, но я не могу обратить внимание на конкретные примеры. На днях я читал еще один вопрос SO, где кто-то жаловался на то, как битовые поля C «в основном бесполезны», и я думал, как элегантно битовые поля C представляют низкоуровневые сетевые протоколы. Высокоуровневые языки, имеющие дело со структурами битов, всегда заканчиваются беспорядком!

-121--2444774-

Для этого необходимо использовать курсор.

DECLARE @oneid int -- or the appropriate type

DECLARE the_cursor CURSOR FAST_FORWARD
FOR SELECT spro.Id  
    FROM SomeTable as spro 
        INNER JOIN [Address] addr ON addr.Id = spro.Id  
        INNER JOIN City cty ON cty.CityId = addr.CityId 
    WHERE cty.CityId = @CityId

OPEN the_cursor
FETCH NEXT FROM the_cursor INTO @oneid

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC UpdateComputedFullText @oneid

    FETCH NEXT FROM the_cursor INTO @oneid
END

CLOSE the_cursor
DEALLOCATE the_cursor
67
ответ дан 26 November 2019 в 20:13
поделиться

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

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

2
ответ дан 26 November 2019 в 20:13
поделиться

Поместите идентификаторы во временную табличную переменную, а затем выполните итерацию по каждому row: (Вам не нужно использовать курсор, который будет значительно медленнее)

   Declare @Keys Table (key integer Primary Key Not Null)
   Insert @Keys(key)
   SELECT spro.Id  
   FROM SomeTable as spro 
       JOIN [Address] addr ON addr.Id = spro.Id  
       JOIN City cty ON cty.CityId = addr.CityId 
   WHERE cty.CityId = @CityId
   -- -------------------------------------------
   Declare @Key Integer
   While Exists (Select * From @Keys)
     Begin
         Select @Key = Max(Key) From @Keys
         EXEC UpdateComputedFullText @Key
         Delete @Keys Where Key = @Key
     End 

EDIT Delete работает не медленно, если используется с предикатом фильтра, управляемым по очень узкому уникальному индексу, как это есть. Но этого легко избежать, просто составив следующий цикл:

Declare @Key Integer = 0
While Exists (Select * From @Keys
              Where key > @Key)
 Begin
     Select @Key = Min(Key) From @Keys
                   Where key > @Key
     EXEC UpdateComputedFullText @Key
     -- Delete @Keys Where Key = @Key No Longer necessary 
 End    
21
ответ дан 26 November 2019 в 20:13
поделиться

Попробуйте это без курсора

DECLARE @id int 

SELECT top 1 @id = spro.Id   
    FROM SomeTable as spro  
        INNER JOIN [Address] addr ON addr.Id = spro.Id   
        INNER JOIN City cty ON cty.CityId = addr.CityId  
    WHERE cty.CityId = @CityId
    ORDER BY spro.id

WHILE @@ROWCOUNT > 0 
BEGIN 
    EXEC UpdateComputedFullText @id 

    SELECT top 1 @id = spro.Id   
    FROM SomeTable as spro  
        INNER JOIN [Address] addr ON addr.Id = spro.Id   
        INNER JOIN City cty ON cty.CityId = addr.CityId  
    WHERE cty.CityId = @CityId 
    and spro.id > @id
    ORDER BY spro.id
END 
5
ответ дан 26 November 2019 в 20:13
поделиться

Вам действительно нужно сделать обработку row-rue, когда установлена ​​обработка?

Вы можете поставить результаты выбора в таблицу TEMP, а затем вызовите ProC для выполнения объемного SQL против содержимого таблицы Temp. Таблица TEMP будет доступна под названием ProC, основанные на правилах Scoping T-SQL.

0
ответ дан 26 November 2019 в 20:13
поделиться

Удивлен, никто не дал вам актуальный ответ. Курсоры плохие. То, что вы хотите, - это переместить логику SP в таблицу-ценную функцию (TVF), а затем использовать Cross Apply

Вот запрос, который я написал вчера (не останавливайтесь на деталях Просто посмотрите на Кресту ). Крест применяется создает союз таблиц. Каждый элемент этого объединения генерируется из TVF, который параметризован на записях строки оператора SELECT.

SELECT supt.hostname,supt.scriptname, COUNT(*)
FROM Event_Pagehit eph
    INNER JOIN Symboltable_urlpair supf
    ON eph.fromPagePair=supf.id
    INNER JOIN Symboltable_urlpair supt
    ON supt.id=eph.toPagePair
CROSS APPLY dbo.TDFCompanyFormationsUrlClassification(supf.hostname,supf.scriptname) as x
CROSS APPLY dbo.TDFCompanyFormationsUrlClassification(supt.hostname,supt.scriptname) as y
WHERE x.isCompanyFormations=1
AND y.isCompanyFormations=0
GROUP BY supt.hostname,supt.scriptname
ORDER BY COUNT(*) desc

Я могу использовать x и y y y y , как если бы они были таблицами, вытянутыми из из или , присоединяются к пунктам . Если бы мне пришлось написать этот запрос без TVF, он будет охватить пару сотен линий.

Примечание.

Если вы не можете переписать SP: вы должны иметь возможность вставить результат сохраненной процедуры в таблицу результатов из таблицы. Я никогда не делал этого, а иногда разные конструкции SQL Server имеют предостережения - поэтому, если кто-то не говорит иначе, я не предполагаю, что это так.

21
ответ дан 26 November 2019 в 20:13
поделиться

Нужно использовать курсор: Примеры курсоров SQL-сервера

DECLARE @id int
DECLARE cursor_sample CURSOR FOR  
SELECT spro.Id 
FROM SomeTable as spro
    INNER JOIN [Address] addr ON addr.Id = spro.Id 
    INNER JOIN City cty ON cty.CityId = addr.CityId
WHERE cty.CityId = @CityId

OPEN cursor_sample
FETCH NEXT FROM cursor_sample INTO @id 
WHILE @@FETCH_STATUS = 0   
BEGIN  
    EXEC UpdateComputedFullText @id
    FETCH NEXT FROM cursor_sample INTO @id
END   

CLOSE cursor_sample
DEALLOCATE cursor_sample
1
ответ дан 26 November 2019 в 20:13
поделиться