Powiedzmy, że mam następującą prostą zmienną tabelową:
declare @databases table
(
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
Czy deklarowanie i używanie kursora jest moją jedyną opcją, jeśli chcę iterować między wierszami? Czy jest inny sposób?
sql-server
tsql
loops
Promień
źródło
źródło
STATIC
opcji, aby usunąć ciągłe ponowne sprawdzanie tabel bazowych i blokowania, które są tam domyślnie i powodują, że większość ludzi błędnie uważa, że KURSORY są złe. @JacquesB bardzo blisko: ponowne sprawdzenie, czy wiersz wyników nadal istnieje + blokowanie to problemy. ISTATIC
zwykle to naprawia :-).Odpowiedzi:
Przede wszystkim powinieneś być absolutnie pewien, że musisz iterować po każdym wierszu - operacje oparte na zestawie wierszy będą działały szybciej w każdym przypadku, o którym mogę pomyśleć i zwykle będą używać prostszego kodu.
W zależności od danych może być możliwe zapętlenie za pomocą
SELECT
instrukcji, jak pokazano poniżej:Inną alternatywą jest użycie tabeli tymczasowej:
Opcja, którą powinieneś wybrać, naprawdę zależy od struktury i objętości twoich danych.
Uwaga: jeśli korzystasz z programu SQL Server, lepiej byś był obsługiwany za pomocą:
Używanie
COUNT
będzie musiało dotykać każdego wiersza w tabeli,EXISTS
wystarczy dotknąć pierwszego (patrz odpowiedź Josefa poniżej).źródło
STATIC
opcji kopiującej zestaw wyników do tabeli tymczasowej, a zatem nie blokujesz już ani nie sprawdzasz ponownie tabel podstawowych :-).Krótka uwaga, jeśli używasz SQL Server (2008 i wyżej), przykłady, które mają:
Lepiej by było
Hrabia będzie musiał dotknąć każdego wiersza w tabeli,
EXISTS
wystarczy dotknąć pierwszego.źródło
Tak to robię:
Bez kursorów, bez tabel tymczasowych, bez dodatkowych kolumn. Kolumna USERID musi być unikalną liczbą całkowitą, podobnie jak większość kluczy podstawowych.
źródło
Zdefiniuj swój stół tymczasowy w ten sposób -
Następnie zrób to -
źródło
Oto jak bym to zrobił:
[Edytuj] Ponieważ prawdopodobnie pominąłem słowo „zmienna”, kiedy po raz pierwszy przeczytałem pytanie, oto zaktualizowana odpowiedź ...
źródło
Jeśli nie masz innego wyboru, niż przejść wiersz po rzędzie, tworząc kursor FAST_FORWARD. Będzie to tak szybkie, jak tworzenie pętli while i znacznie łatwiejsze w utrzymaniu na dłuższą metę.
FAST_FORWARD Określa kursor FORWARD_ONLY, READ_ONLY z włączoną optymalizacją wydajności. FAST_FORWARD nie może zostać określony, jeśli określono również SCROLL lub FOR_UPDATE.
źródło
FAST_FORWARD
Kursor jest rozwiązaniem dobrze. (opinia pozytywna)Inne podejście bez konieczności zmiany schematu lub korzystania z tabel tymczasowych:
źródło
Możesz użyć pętli while:
źródło
Będzie to działać w wersji SQL SERVER 2012.
źródło
Lekki, bez konieczności tworzenia dodatkowych tabel, jeśli masz
ID
na stole liczbę całkowitąźródło
źródło
Naprawdę nie widzę sensu, dlaczego musiałbyś uciekać się do używania przerażającego
cursor
. Ale jest inna opcja, jeśli używasz SQL Server w wersji 2005/2008Użyj rekurencji
źródło
Zamierzam dostarczyć rozwiązanie oparte na zestawie.
Jest to znacznie szybsze niż jakakolwiek technika zapętlania i jest łatwiejsze do napisania i utrzymania.
źródło
Wolę używać funkcji Offset Fetch, jeśli masz unikalny identyfikator, dzięki któremu możesz posortować tabelę według:
W ten sposób nie muszę dodawać pól do tabeli ani używać funkcji okna.
źródło
Można to zrobić za pomocą kursora:
funkcja tworzenia [dbo] .f_teste_loop zwraca tabelę @tabela (cod int, nome varchar (10)) jak początek
koniec
utwórz procedurę [dbo]. [sp_teste_loop] jak zacząć
koniec
źródło
Zgadzam się z poprzednim postem, że operacje oparte na zestawach będą zazwyczaj działały lepiej, ale jeśli musisz iterować wiersze, oto podejście, które wybrałbym:
Wybierz następny nieużywany rekord z tabeli i powtórz proces
źródło
Krok 1: Poniższa instrukcja select tworzy tabelę temp z unikalnym numerem wiersza dla każdego rekordu.
Krok 2: Zadeklaruj wymagane zmienne
Krok 3: Pobierz całkowitą liczbę wierszy z tabeli temp
Krok 4: Tabela temp. Pętli oparta na unikalnym numerze wiersza utworzona w temp
źródło
To podejście wymaga tylko jednej zmiennej i nie usuwa żadnych wierszy z @ baz danych. Wiem, że jest tu wiele odpowiedzi, ale nie widzę takiej, która używa MIN, aby uzyskać twój następny identyfikator w ten sposób.
źródło
Oto moje rozwiązanie, które korzysta z nieskończonej pętli,
BREAK
instrukcji i@@ROWCOUNT
funkcji. Nie są wymagane żadne kursory ani tabela tymczasowa i muszę tylko napisać jedno zapytanie, aby uzyskać następny wiersz w@databases
tabeli:źródło
To jest kod, którego używam 2008 R2. Ten kod, którego używam, służy do tworzenia indeksów na kluczowych polach (SSNO i EMPR_NO) we wszystkich opowieściach
źródło
byłoby lepiej:
Unikaj używania WYBIERZ, jeśli nie odwołujesz się do tabel, tylko przypisujesz wartości.
źródło