Курсор в курсоре

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

[JsonProperty]
public IEnumerable<T> Elements {
    get 
    { 
       return this; 
    }
}
27
задан Joel Coehoorn 22 January 2009 в 15:36
поделиться

5 ответов

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

FETCH NEXT FROM INNER_CURSOR

WHILE (@@FETCH_STATUS <> -1)
BEGIN

UPDATE CONTACTS
SET INDEX_NO = @COUNTER
WHERE CURRENT OF INNER_CURSOR

SET @COUNTER = @COUNTER + 1

FETCH NEXT FROM INNER_CURSOR
FETCH NEXT FROM INNER_CURSOR
END
0
ответ дан Orkun Balkancı 14 October 2019 в 12:48
поделиться

У Вас есть множество проблем. Во-первых, почему Вы используете свое определенное @@ значения FETCH_STATUS? Это должно просто быть @@ FETCH_STATUS = 0.

114-секундный, Вы не выбираете свой внутренний Курсор в ничто. И я не могу думать ни о каком обстоятельстве, где Вы выбрали бы все поля таким образом - обстоятельно объясняют их!

Вот образец, чтобы пройти. Папка имеет первичный ключ "ClientID", который является также внешним ключом для, Принимают участие. Я просто печатаю все Посещение UIDs, сломанного Папкой ClientID:

Declare @ClientID int;
Declare @UID int;

DECLARE Cur1 CURSOR FOR
    SELECT ClientID From Folder;

OPEN Cur1
FETCH NEXT FROM Cur1 INTO @ClientID;
WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'Processing ClientID: ' + Cast(@ClientID as Varchar);
    DECLARE Cur2 CURSOR FOR
        SELECT UID FROM Attend Where ClientID=@ClientID;
    OPEN Cur2;
    FETCH NEXT FROM Cur2 INTO @UID;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT 'Found UID: ' + Cast(@UID as Varchar);
        FETCH NEXT FROM Cur2 INTO @UID;
    END;
    CLOSE Cur2;
    DEALLOCATE Cur2;
    FETCH NEXT FROM Cur1 INTO @ClientID;
END;
PRINT 'DONE';
CLOSE Cur1;
DEALLOCATE Cur1;

Наконец, Вы УВЕРЕННЫЙ , Вы хотите сделать что-то вроде этого в хранимой процедуре? Это очень легко злоупотребить хранимыми процедурами и часто отражает проблемы в охарактеризовании Вашей проблемы. Образец, который я дал, например, мог быть намного более легко выполнен с помощью стандартных избранных вызовов.

62
ответ дан Mark Brittingham 14 October 2019 в 12:48
поделиться

Вы больше делаете выборки? Необходимо показать тем также. Вы только показываете нам половину кода.

Это должно быть похожим:

FETCH NEXT FROM @Outer INTO ...
WHILE @@FETCH_STATUS = 0
BEGIN
  DECLARE @Inner...
  OPEN @Inner
  FETCH NEXT FROM @Inner INTO ...
  WHILE @@FETCH_STATUS = 0
  BEGIN
  ...
    FETCH NEXT FROM @Inner INTO ...
  END
  CLOSE @Inner
  DEALLOCATE @Inner
  FETCH NEXT FROM @Outer INTO ...
END
CLOSE @Outer
DEALLOCATE @Outer

кроме того, удостоверьтесь, что Вы не называете курсоры тем же..., и любой код (проверьте свои триггеры), который называют, не использует курсор, который называют тем же. Я видел нечетное поведение от людей, использующих 'theCursor' в нескольких слоях стека.

2
ответ дан Amy B 14 October 2019 в 12:48
поделиться

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

declare @rowid int
declare @rowid2 int
declare @id int
declare @type varchar(10)
declare @rows int
declare @rows2 int
declare @outer table (rowid int identity(1,1), id int, type varchar(100))
declare @inner table (rowid int  identity(1,1), clientid int, whatever int)

insert into @outer (id, type) 
Select id, type from sometable

select @rows = count(1) from @outer
while (@rows > 0)
Begin
    select top 1 @rowid = rowid, @id  = id, @type = type
    from @outer
    insert into @innner (clientid, whatever ) 
    select clientid whatever from contacts where contactid = @id
    select @rows2 = count(1) from @inner
    while (@rows2 > 0)
    Begin
        select top 1 /* stuff you want into some variables */
        /* Other statements you want to execute */
        delete from @inner where rowid = @rowid2
        select @rows2 = count(1) from @inner
    End  
    delete from @outer where rowid = @rowid
    select @rows = count(1) from @outer
End
10
ответ дан cmsjr 14 October 2019 в 12:48
поделиться

Это пахнет чем-то, что должно быть сделано с СОЕДИНЕНИЕМ вместо этого. Можно ли совместно использовать большую проблему с нами?

<час>

Эй, я должен быть в состоянии свалить это к отдельному оператору, но я не имел времени для игры с ним далее все же сегодня и не могу добраться до. Тем временем знайте, что необходимо быть в состоянии отредактировать запрос для внутреннего курсора для создания номеров строк как части запроса с помощью ROW_NUMBER () функция. Оттуда, можно свернуть внутренний курсор во внешнее путем выполнения ВНУТРЕННЕГО ОБЪЕДИНЕНИЯ на нем (можно присоединиться на запросе sub). Наконец, любой оператор SELECT может быть преобразован в ОБНОВЛЕНИЕ с помощью этого метода:

UPDATE [YourTable/Alias]
   SET [Column] = q.Value
FROM
(
   ... complicate select query here ...
) q

, Где [YourTable/Alias] таблица или псевдоним, используемый в запросе Select.

2
ответ дан Joel Coehoorn 14 October 2019 в 12:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: