2016-12-23 11 views
6

мне нужна некоторые примеры для @@fetch_status значений -2 иКаковы примеры @@ FETCH_STATUS значение -2 и -9

0 = The FETCH statement was successful. 
    -1 = The FETCH statement failed or the row was beyond the result set. 

Вот пример выборки курсора

declare @country varchar(50) 
declare cur_country cursor for 
    select name from global 
open cur_country 

fetch next from cur_country into @country 
    print @@FETCH_STATUS 
while (@@FETCH_STATUS=0) 
begin 
insert into country select @country 
fetch next from cur_country into @country 
end 

close cur_country 
deallocate cur_country. 

-2 строка, отсутствует. Курсор не выполняет операцию выборки.

в основном нужен сценарий, где @@FETCH_STATUS дает -2 0r

+0

И пример -9 здесь http://stackoverflow.com/questions/36271942/what-does-the-value-9-means-for-fetch-status-in-sql-server – DVT

+0

@ syncdm2012 у вас есть удивительный ответ от dlatikay. почему еще не ответили или не приняли этот ответ!Не обращая внимания на другие усилия, не является хорошим – Hadi

ответ

8

@@FETCH_STATUS = -2 обычно происходит, когда какой-то процесс ВНЕ курсора удаляет строку в таблице курсор на основе.

Если задание 1 открывает курсор и начинает цикл по записям в таблице1, а во время выполнения задания 1 выполняется задание 2 и удаляет определенные записи в таблице1, задание 1 может вернуть значение -2, когда оно пытается получить строку он ожидал найти (потому что он был там, когда начал курсор).

Следующая Topic содержит пример @@FETCH_STATUS = -2

При исследовании я нашел следующее объяснение от этого Topic:

«Указывает, что членство и порядок строк в курсоре фиксируются, когда курсор открывается набор ключей, которые однозначно идентифицируют строки: , встроенный в таблицу в tempdb, известную как набор ключей. Изменения в значениях без ключа в базовых таблицах, сделанные владельцем указателя или совершенные другимиПользователивидны, когда владелец прокручивает курсор. Вставки, сделанные , другие пользователи не видны (вставки не могут быть выполнены с помощью курсора сервера Transact-SQL ). Если строка удалена, попытка получить строку возвращает @@ FETCH_STATUS -2. Обновления значений ключа из-за пределов курсора напоминают удаление старой строки, за которой следует вставка новой строки. Строка с новые значения не видны, и попытки получить строку со старыми значениями возвращают @@ FETCH_STATUS -2. Новые значения видны, если обновление осуществляется с помощью курсора, указав WHERE CURRENT OF пункта»

И как DVT комментировал. Это Stackoverflow question содержит пример на @@FETCH_STATUS = -9

Более подробную информацию о @@FETCH_STATUS может быть нашли в этом MSDN article

+1

объявить v_country VARCHAR (50) объявить cur_country курсор для выберите имя из глобального открытого cur_country выборки рядом с cur_country в v_country в то время как (@@ FETCH_STATUS = 0) начать вставку в стране выберите v_country WAITFOR DELAY '00: 00: 12' печати @@ FETCH_STATUS выборки рядом с cur_country в v_country конца близко cur_country DEALLOCATE cur_country создал еще один сеанс удаляется запись, но не работает @@ FETCH_STATUS не приходит, как -2 – syncdm2012

+1

@ syncdm2012, вам нужно будет убедиться, что вы используете таблицу с хотя бы одним уникальным индексом/первичным ключом: в противном случае курсор по умолчанию использует курсор 'STATIC', что означает, что временная копия набора результатов кэшируется 'OPEN', и вы никогда не увидите эффект (по дизайну, https://msdn.microsoft.com/de-at/library/ms180169.aspx). Кстати. Именование вашей таблицы «global» довольно запутанно, поскольку «GLOBAL» также является необязательным ключевым словом синтаксиса курсора. – dlatikay

2

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

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 

Результат:

scenario returning minus two

Это будет работать только то же самое при запуске в одной партии, в том же соединении, с DELETE непосредственно перед вторым FETCH. Установка с двумя соединениями демонстрирует его в реалистичном контексте, предполагая, что разработчик, знающий ключевое слово KEYSET, не будет специально удалять при извлечении и не будет иметь побочных эффектов в цикле курсора, вызывающих такие удаления (с использованием как курсоров, так и триггеров та же мерзость, что и манипулирование html с регулярным выражением).

+0

Хорошие примеры. Вы заслуживаете щедрости. Надеюсь, что этот ответ будет принят – Hadi