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:
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).
Przykład -9 tutaj http://stackoverflow.com/questions/36271942/what-does-the-value-9-means-for-fetch-status-in-sql-server – DVT
@ 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