Angenommen, ich habe die folgende einfache Tabellenvariable:
declare @databases table
(
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
Ist das Deklarieren und Verwenden eines Cursors meine einzige Option, wenn ich die Zeilen durchlaufen möchte? Gibt es eine andere Art und Weise?
sql-server
tsql
loops
Strahl
quelle
quelle
STATIC
Option verwenden, um die ständige Überprüfung der Basistabellen und die Sperren, die standardmäßig vorhanden sind, zu entfernen und die meisten Leute fälschlicherweise glauben zu lassen, dass CURSORs böse sind. @JacquesB ganz in der Nähe: Überprüfen Sie erneut, ob die Ergebniszeile noch vorhanden ist. + Sperren sind die Probleme. UndSTATIC
normalerweise behebt das :-).Antworten:
Zuallererst sollten Sie absolut sicher sein, dass Sie jede zeilensatzbasierte Operation durchlaufen müssen. Sie wird in jedem denkbaren Fall schneller ausgeführt und verwendet normalerweise einfacheren Code.
Abhängig von Ihren Daten kann es möglich sein, nur die folgenden
SELECT
Anweisungen zu verwenden:Eine andere Alternative ist die Verwendung einer temporären Tabelle:
Die Option, die Sie auswählen sollten, hängt wirklich von der Struktur und dem Volumen Ihrer Daten ab.
Hinweis: Wenn Sie SQL Server verwenden, sollten Sie Folgendes verwenden:
Mit
COUNT
muss jede einzelne Zeile in der Tabelle berührt werden, dieEXISTS
einzige muss nur die erste berühren (siehe Josefs Antwort unten).quelle
STATIC
Option verwenden, mit der die Ergebnismenge in eine temporäre Tabelle kopiert wird, und daher werden Basistabellen nicht mehr gesperrt oder erneut überprüft :-).Nur eine kurze Anmerkung, wenn Sie SQL Server (2008 und höher) verwenden, die folgenden Beispiele:
Wäre besser mit serviert
Der Count muss jede einzelne Zeile in der Tabelle
EXISTS
berühren , die einzige muss nur die erste berühren.quelle
So mache ich es:
Keine Cursor, keine temporären Tabellen, keine zusätzlichen Spalten. Die USERID-Spalte muss eine eindeutige Ganzzahl sein, wie es die meisten Primärschlüssel sind.
quelle
Definieren Sie Ihre temporäre Tabelle wie folgt:
Dann mach das -
quelle
So würde ich es machen:
[Bearbeiten] Da ich beim ersten Lesen der Frage wahrscheinlich das Wort "Variable" übersprungen habe, finden Sie hier eine aktualisierte Antwort ...
quelle
Wenn Sie keine andere Wahl haben, als Zeile für Zeile einen FAST_FORWARD-Cursor zu erstellen. Es ist so schnell wie der Aufbau einer while-Schleife und auf lange Sicht viel einfacher zu warten.
FAST_FORWARD Gibt einen FORWARD_ONLY-, READ_ONLY-Cursor mit aktivierten Leistungsoptimierungen an. FAST_FORWARD kann nicht angegeben werden, wenn auch SCROLL oder FOR_UPDATE angegeben ist.
quelle
FAST_FORWARD
Cursor ist eine feine Lösung. (Gegenstimme)Ein anderer Ansatz, ohne dass Sie Ihr Schema ändern oder temporäre Tabellen verwenden müssen:
quelle
Sie können eine while-Schleife verwenden:
quelle
Dies funktioniert in der SQL Server 2012-Version.
quelle
Leicht, ohne zusätzliche Tabellen erstellen zu müssen, wenn Sie eine Ganzzahl
ID
auf der Tabelle habenquelle
quelle
Ich verstehe wirklich nicht den Punkt, warum Sie auf gefürchtete zurückgreifen müssten
cursor
. Wenn Sie SQL Server Version 2005/2008 verwenden, verwendenSie die Rekursion
quelle
Ich werde die setbasierte Lösung bereitstellen.
Dies ist weitaus schneller als jede Schleifentechnik und einfacher zu schreiben und zu warten.
quelle
Ich bevorzuge die Verwendung des Offset-Abrufs, wenn Sie eine eindeutige ID haben, nach der Sie Ihre Tabelle sortieren können:
Auf diese Weise muss ich der Tabelle keine Felder hinzufügen oder eine Fensterfunktion verwenden.
quelle
Hierzu kann ein Cursor verwendet werden:
create function [dbo] .f_teste_loop gibt als Anfang die Tabelle @tabela (cod int, nome varchar (10)) zurück
Ende
Erstellen Sie die Prozedur [dbo]. [sp_teste_loop] als Beginn
Ende
quelle
Ich stimme dem vorherigen Beitrag zu, dass satzbasierte Operationen normalerweise eine bessere Leistung erbringen. Wenn Sie jedoch die Zeilen durchlaufen müssen, würde ich folgende Vorgehensweise wählen:
Wählen Sie den nächsten nicht verwendeten Datensatz aus der Tabelle aus und wiederholen Sie den Vorgang
quelle
Schritt 1: Unter der select-Anweisung wird eine temporäre Tabelle mit einer eindeutigen Zeilennummer für jeden Datensatz erstellt.
Schritt 2: Deklarieren Sie die erforderlichen Variablen
Schritt 3: Nehmen Sie die Gesamtzahl der Zeilen aus der temporären Tabelle
Schritt 4: Schleifentemp-Tabelle basierend auf der in Temp erstellten eindeutigen Zeilennummer
quelle
Dieser Ansatz erfordert nur eine Variable und löscht keine Zeilen aus @databases. Ich weiß, dass es hier viele Antworten gibt, aber ich sehe keine, die MIN verwendet, um Ihre nächste ID wie diese zu erhalten.
quelle
Hier ist meine Lösung, die eine Endlosschleife, die
BREAK
Anweisung und die@@ROWCOUNT
Funktion verwendet. Es sind keine Cursor oder temporäre Tabellen erforderlich, und ich muss nur eine Abfrage schreiben, um die nächste Zeile in der@databases
Tabelle zu erhalten:quelle
Dies ist der Code, den ich 2008 R2 verwende. Dieser Code, den ich verwende, dient zum Erstellen von Indizes für Schlüsselfelder (SSNO & EMPR_NO) in allen Geschichten
quelle
wäre besser:
Vermeiden Sie die Verwendung von SELECT, wenn Sie nicht auf Tabellen verweisen, sondern nur Werte zuweisen.
quelle