Изтриване на ред от източника на курсора SQL Server

Имам курсор на SQL Server 2005, работещ върху променлива на таблица, наречена @workingSet.

Понякога редовете могат да бъдат свързани и в този случай аз обработвам реда, който съм извлякъл, и свързаните редове едновременно. След това премахвам свързаните записи от @workingset, тъй като не е необходимо да обработвам след това в цикъла.

В @workingSet със 7 реда, първите два са свързани, така че когато обработвам 1, обработвам и 2. Премахвам ред 2 от източника на курсора (@workingSet) и след това извличам следващия. Проблемът е, че връща втория ред в @workingset (този, който изтрих при предишната итерация).

Останах с впечатлението, че това може да се направи, т.е. изтриване на елемент от източник, върху който работи курсор, и той ще уважи изтриването при последващи извличания.


person Simon Rigby    schedule 05.10.2011    source източник
comment
Можете ли да ни покажете какво правите?? Най-добрият вариант би бил да елиминирате напълно курсора - което е възможно в поне 90% от всички случаи...   -  person marc_s    schedule 05.10.2011
comment
Благодаря и да, прав си .. и все още не съм убеден, че курсорът е необходим, но ми беше по-интересно да знам, че е възможно.   -  person Simon Rigby    schedule 06.10.2011


Отговори (2)


Отговорът изглежда е, че променливата на таблицата, която се използва като източник на курсора, трябва да има първичен ключ. Добавих това и всичко работи правилно.

person Simon Rigby    schedule 06.10.2011
comment
Таблицата в моя отговор няма PK и отразява правилно резултатите от DELETE. - person Martin Smith; 06.10.2011
comment
Здравейте .. да, успях да направя доказателство за концепцията без PK и то работи правилно. Не знам защо в другия случай го изисква. - person Simon Rigby; 06.10.2011
comment
Имате ли зададени други опции за курсора? - person Martin Smith; 06.10.2011
comment
Здравей Мартин .. не .. няма опции за курсора .. по подразбиране докрай. Не съм убеден, че това е отговорът, поради което не съм го маркирал. - person Simon Rigby; 26.10.2011
comment
Мисля, че намерих обяснението. Имате нужда от динамичен курсор, за да имате промените в изходната таблица, отразени в извличането на курсора. Получавахте имплицитно преобразуване към keyset или static курсор. Вероятно, тъй като сте подреждали по неиндексирана колона. Има ли ORDER BY във вашата заявка в колоната PK? Получавам същото поведение в заявката в моя отговор, ако добавя ORDER BY C към SELECT - person Martin Smith; 30.10.2011

Не сте добре запознати с курсорите, но от бърз тест в този край трябва да избягвате декларирането на курсора с опциите STATIC или KEYSET, тогава промените в основната таблица се отразяват в курсора.

SET NOCOUNT ON;

DECLARE @WorkingTable TABLE(C int)

INSERT INTO @WorkingTable VALUES (1),(2),(3)

DECLARE @C int

DECLARE wt_cursor CURSOR 
DYNAMIC /*Or left blank but not STATIC or KEYSET*/
FOR 
SELECT C
FROM @WorkingTable

OPEN wt_cursor;

FETCH NEXT FROM wt_cursor 
INTO @C

DELETE FROM @WorkingTable

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @C;


    FETCH NEXT FROM wt_cursor 
    INTO @C;
END
CLOSE wt_cursor;
DEALLOCATE wt_cursor;
person Martin Smith    schedule 05.10.2011
comment
Благодаря .. да, курсорът не е деклариран със STATIC или KEYSET. - person Simon Rigby; 06.10.2011
comment
@Simon - Какво получавате, когато стартирате кода в моя отговор, но изтриете опцията DYNAMIC? За мен просто връща 1 не 1,2,3 - person Martin Smith; 06.10.2011