Обычно минимальные полные сверяемые примеры должны быть частью хорошего вопроса Здесь я попытаюсь ответить с двумя из них:.
1.Минимальный сценарий курсора, который даст -9 («не выборка»)
Отметьте, что @@FETCH_STATUS
сам никогда не примет это значение (оно вернет 0). Только внутренние структуры управления имеют это как начальное значение для объявленных и никогда не получаемых курсоров (независимо от того, открыто или нет).
DECLARE [cursor-9] CURSOR FOR SELECT null FROM sys.tables
SELECT [fetch_status] FROM sys.dm_exec_cursors(@@SPID) WHERE name='cursor-9'
DEALLOCATE [cursor-9]
Далее ссылка: https://stackoverflow.com/a/36272354/1132334
2. Минимальный сценарий курсора, который будет возвращать -2 ("строка отсутствует")
Это требует два соединения для параллельной обработки. Я использовал два экземпляра SSMS, подключенных к 11.0.6020 с одним окном сценария, каждый, подключенный к одной и той же пустой базе данных.
Выполнить этот сценарий в первую очередь:
DECLARE @@id int
CREATE TABLE tmp41307323 (
Id int not null PRIMARY KEY
)
INSERT INTO tmp41307323 (Id) VALUES (1),(2)
DECLARE [cursor-2] CURSOR KEYSET FOR SELECT Id FROM tmp41307323 ORDER BY Id
OPEN [cursor-2]
FETCH NEXT FROM [cursor-2] INTO @@id
Это создаст таблицу с первичным ключом, добавьте две строки, и открыть курсор на набор ключей него. Без ключевого слова KEYSET
вы получите -1 вместо -2, потому что именно так работают ключи: SQL Server создает временную таблицу в tempdb, которая содержит только упорядоченные уникальные значения ключей для каждой строки, которую выбирает курсор. Затем, когда мы получаем, он просматривает ключи следующей строки для извлечения во временную таблицу и выбирает только эту строку из реальной таблицы. Это, и только это, сценарий поэтому восприимчив к одновременным удалениям. Кроме того, он увидит изменения, внесенные в любые неявные столбцы исходной таблицы, сделанные при извлечении.
Выполнить этот скрипт во втором случае:
DELETE FROM tmp41307323 WHERE Id=2
Таким образом, мы удалить строку, курсор в первую очередь было бы ожидать, чтобы увидеть, когда он получает следующий.
Наконец, запустите этот сценарий в первую очередь (не отсоединять, чтобы курсор будет по-прежнему находиться в области видимости):
DECLARE @@id int
FETCH NEXT FROM [cursor-2] INTO @@id
SELECT @@FETCH_STATUS [@@FETCH_STATUS]
CLOSE [cursor-2]
DEALLOCATE [cursor-2]
DROP TABLE tmp41307323
Результат:
Это будет работать только то же самое при запуске в одной партии, в том же соединении, с DELETE
непосредственно перед вторым FETCH
. Установка с двумя соединениями демонстрирует его в реалистичном контексте, предполагая, что разработчик, знающий ключевое слово KEYSET
, не будет специально удалять при извлечении и не будет иметь побочных эффектов в цикле курсора, вызывающих такие удаления (с использованием как курсоров, так и триггеров та же мерзость, что и манипулирование html с регулярным выражением).
И пример -9 здесь http://stackoverflow.com/questions/36271942/what-does-the-value-9-means-for-fetch-status-in-sql-server – DVT
@ syncdm2012 у вас есть удивительный ответ от dlatikay. почему еще не ответили или не приняли этот ответ!Не обращая внимания на другие усилия, не является хорошим – Hadi