2016-12-23 62 views
6

potrzebne pewne przykłady @@fetch_status wartości -2 iCo są przykładami @@ wartość FETCH_STATUS -2 i -9

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

Tutaj jest przykład próbka CURSOR

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 Wiersz pobrano brak. Kursor nie wykonuje operacji pobierania.

zasadniczo muszą scenariusz, w którym @@FETCH_STATUS daje -2 0R

+0

Przykład -9 tutaj http://stackoverflow.com/questions/36271942/what-does-the-value-9-means-for-fetch-status-in-sql-server – DVT

+0

@ syncdm2012 masz niesamowita odpowiedź od dlatikay. dlaczego nadal nie odpowiada lub akceptuje tę odpowiedź!Ignorując pozostały wysiłków nie jest dobre – Hadi

Odpowiedz

8

@@FETCH_STATUS = -2 zwykle dzieje się, gdy część procesu ZEWNĘTRZNE kursora usuwa wiersz w tabeli, kursor jest oparte.

Jeśli zadanie 1 powoduje otwarcie kursora i rozpoczyna przechodzenie przez zapisy w tabeli1, a gdy zadanie 1 jest zapętlone, pojawia się zadanie 2 i usuwa określone rekordy w tabeli 1, zadanie 1 może zwrócić wartość -2 podczas próby pobrania wiersza spodziewał się znaleźć (ponieważ był tam, gdy kursor się uruchomił).

Poniższy Topic zawiera przykładowy @@FETCH_STATUS = -2

Badając znalazłem następujące wyjaśnienie z tego Topic:

„określa, że ​​skład i kolejność wierszy w kursora są stałe podczas kursor Zestaw kluczy, które jednoznacznie identyfikują wiersze, to wbudowany w tabelę w tempdb, znaną jako zestaw kluczy, który zmienia wartości nie-kluczy w tabelach bazowych, wprowadzonych przez właściciela kursora lub przez innego użytkownika użytkowników są widoczne, gdy właściciel przewija kursor. Inserty wykonane przez inni użytkownicy nie są widoczni (wkładki nie mogą być wykonane za pomocą kursora serwera Transact-SQL ). Jeśli wiersz zostanie usunięty, próba pobrania tego wiersza zwraca wartość @@ FETCH_STATUS równą -2. Aktualizacja wartości klucza spoza kursora przypomina usunięcie starego wiersza, po którym następuje wstawienie nowego wiersza. Wiersz z nowych wartości nie jest widoczny, a próby pobrania wiersza ze starymi wartościami zwracają wartość @@ FETCH_STATUS równą -2. Nowe wartości są widoczne, jeśli aktualizacja odbywa się za pomocą kursora, określając gdzie obecna klauzuli”

I jak DVT skomentował. Ten Stackoverflow question zawiera przykład na @@FETCH_STATUS = -9

Więcej informacji o @@FETCH_STATUS może być znaleźć pod tym MSDN article

+1

stwierdzenie v_country varchar (50) stwierdzenie cur_country kursor na Wybierz nazwę z globalnym otwartym cur_country zwrcania obok z cur_country do v_country while (@@ FETCH_STATUS = 0) rozpocząć wkładkę na kraj Wybierz v_country waitfor DELAY '00: 00: 12' druku @@ FETCH_STATUS pobrać następny z cur_country do v_country końcowego blisko cur_country Deallocate cur_country utworzona kolejna sesja rekord, ale nie działa usunięte @@ nie FETCH_STATUS przyjście jako -2 – syncdm2012

+1

@ syncdm2012 cóż, musisz upewnić się, że używasz tabeli z co najmniej jednym unikalnym indeksem/kluczem podstawowym: w przeciwnym razie kursor domyślnie wskaże kursor 'STATIC', co oznacza, że ​​tymczasowa kopia zestawu wyników jest buforowana 'OPEN', i nigdy nie widać efektu (według projektu, https://msdn.microsoft.com/de-at/library/ms180169.aspx). btw. nazwanie twojej tabeli 'global' jest dość mylące, ponieważ' GLOBAL' jest także opcjonalnym słowem kluczowym składni kursora. – dlatikay

2

zwykle minimalne kompletne verifyable przykłady mają być częścią dobrego pytanie Tutaj postaram się odpowiedzieć na dwa z nich.

1.Minimalny scenariusz kursora, który daje -9 ("nie ściąganie")

Pamiętaj, że sama @@FETCH_STATUS nigdy nie przyjmie tej wartości (zwróci 0). Tylko wewnętrzne struktury kontrolne mają to jako wartość początkową dla kursorów zadeklarowanych i nigdy nie pobranych (niezależnie od tego, czy są otwarte czy nie).

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] 

Dalsze odniesienia: https://stackoverflow.com/a/36272354/1132334

2. Minimalne scenariusz kursor, który powróci -2 ("rząd brak")

Wymaga dwa złącza do współbieżności. Użyłem dwóch wystąpień SSMS, połączonych z 11.0.6020 z jednym okienkiem skryptowym, połączonym z tą samą pustą bazą danych.

Uruchom ten skrypt w pierwszej kolejności:

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 

To spowoduje utworzenie tabeli z klucza podstawowego, dodać dwa wiersze, a następnie otwórz kursor Keyset na nim. Bez słowa kluczowego KEYSET otrzymasz -1 zamiast -2, ponieważ tak działa zestaw kluczy: SQL Server tworzy tymczasową tabelę w tempdb, która przechowuje tylko uporządkowane unikalne wartości kluczy dla każdego wiersza, który wybiera kursor. Następnie, podczas pobierania, wyszukuje klucze następnego rzędu, aby pobrać w tabeli tymczasowej, i wybiera tylko ten wiersz z prawdziwej tabeli. Ten i tylko ten scenariusz jest zatem podatny na równoczesne usuwanie. Poza tym, zobaczysz zmiany dokonane w kolumnach innych niż kluczowe tabeli źródłowej podczas pobierania.

Uruchom ten skrypt w drugiej instancji:

DELETE FROM tmp41307323 WHERE Id=2 

więc usuwamy wiersz kursor w pierwszej instancji spodziewałby się zobaczyć, kiedy to pobiera następny.

Wreszcie uruchomić ten skrypt w pierwszej instancji (nie odłączać więc kursor nadal będzie w zakresie):

DECLARE @@id int 
FETCH NEXT FROM [cursor-2] INTO @@id 
SELECT @@FETCH_STATUS [@@FETCH_STATUS] 
CLOSE [cursor-2] 
DEALLOCATE [cursor-2] 

DROP TABLE tmp41307323 

Wynik:

scenario returning minus two

To będzie działać tylko taki sam, gdy jest uruchamiany w jednej partii, w tym samym połączeniu, z DELETE tuż przed drugim FETCH. Konfiguracja z dwoma połączeniami demonstruje to w realistycznym kontekście, zakładając, że programista znający słowo kluczowe nie będzie celowo usuwał podczas pobierania i nie będzie miał efektów ubocznych w pętli kursora powodujących takie usunięcia (przy użyciu zarówno kursorów, jak i wyzwalaczy). ta sama obrzydliwość, jak i manipulowanie html z regex).

+0

Dobre przykłady. Zasługujesz na nagrodę. Mam nadzieję, że ta odpowiedź zostanie przyjęta – Hadi