Wie speichere ich einen ausgewählten Feldwert in einer Variablen aus einer Abfrage und verwende ihn in einer Aktualisierungsanweisung?
Hier ist meine Vorgehensweise:
Ich schreibe eine gespeicherte SQL Server 2005 T-SQL-Prozedur, die Folgendes ausführt:
- Ruft eine Liste der Rechnungs-IDs aus der Rechnungstabelle ab und speichert sie im Cursor
- Abrufen der Rechnungs-ID vom Cursor -> Variable tmp_key
- foreach tmp_key findet die primäre Kontakt-ID des Rechnungsclients aus der Kundentabelle
- Aktualisiert den Client-Kontaktschlüssel mit der primären Kontakt-ID
- Cursor schließen
Hier ist mein Code:
DECLARE @tmp_key int
DECLARE @get_invckey cursor
set @get_invckey = CURSOR FOR
select invckey from tarinvoice where confirmtocntctkey is null and tranno like '%115876'
OPEN @get_invckey
FETCH NEXT FROM @get_invckey into @tmp_key
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT c.PrimaryCntctKey as PrimaryContactKey
from tarcustomer c, tarinvoice i
where i.custkey = c.custkey and i.invckey = @tmp_key
UPDATE tarinvoice set confirmtocntctkey = PrimaryContactKey where invckey = @tmp_key
FETCH NEXT FROM @get_invckey INTO @tmp_key
END
CLOSE @get_invckey
DEALLOCATE @get_invckey
Wie speichere ich den PrimaryContactKey und verwende ihn erneut in der set-Klausel der folgenden Update-Anweisung? Erstelle ich eine Cursor-Variable oder nur eine andere lokale Variable mit einem int-Typ?
Antworten:
DECLARE @tmp_key int DECLARE @get_invckey cursor SET @get_invckey = CURSOR FOR SELECT invckey FROM tarinvoice WHERE confirmtocntctkey IS NULL AND tranno LIKE '%115876' OPEN @get_invckey FETCH NEXT FROM @get_invckey INTO @tmp_key DECLARE @PrimaryContactKey int --or whatever datatype it is WHILE (@@FETCH_STATUS = 0) BEGIN SELECT @PrimaryContactKey=c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key FETCH NEXT FROM @get_invckey INTO @tmp_key END CLOSE @get_invckey DEALLOCATE @get_invckey
EDIT:
Diese Frage hat viel mehr Zugkraft bekommen, als ich erwartet hätte. Beachten Sie, dass ich in meiner Antwort nicht die Verwendung des Cursors befürworte, sondern zeige, wie der Wert basierend auf der Frage zugewiesen wird.
quelle
Ich hatte gerade das gleiche Problem und ...
declare @userId uniqueidentifier set @userId = (select top 1 UserId from aspnet_Users)
oder noch kürzer:
declare @userId uniqueidentifier SELECT TOP 1 @userId = UserId FROM aspnet_Users
quelle
set @userId = (select top 1 UserId from aspnet_Users)
ohne Klammer führt dies zu "falscher Syntax in der Nähe von select"!Versuche dies
SELECT @PrimaryContactKey = c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key FETCH NEXT FROM @get_invckey INTO @tmp_key
Sie würden diese Variable außerhalb Ihrer Schleife nur als Standard-TSQL-Variable deklarieren.
Ich sollte auch beachten, dass Sie dies für jede Art der Auswahl in einer Variablen tun würden, nicht nur, wenn Sie sich mit Cursorn befassen.
quelle
Warum brauchst du überhaupt einen Cursor? Ihr gesamtes Codesegment kann durch dieses ersetzt werden, das in einer großen Anzahl von Zeilen viel schneller ausgeführt wird.
UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey WHERE confirmtocntctkey is null and tranno like '%115876'
quelle
Um eine Variable sicher zuzuweisen, müssen Sie die Anweisung SET-SELECT verwenden:
SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key)
Stellen Sie sicher, dass Sie sowohl eine Start- als auch eine Endklammer haben!
Es gibt zwei Gründe, warum die SET-SELECT-Version die sicherste Methode zum Festlegen einer Variablen ist.
1. Das SELECT gibt mehrere Beiträge zurück
Was passiert, wenn die folgende Auswahl zu mehreren Posts führt?
SELECT @PrimaryContactKey = c.PrimaryCntctKey FROM tarcustomer c, tarinvoice i WHERE i.custkey = c.custkey AND i.invckey = @tmp_key
@PrimaryContactKey
wird der Wert aus dem letzten Beitrag im Ergebnis zugewiesen .Tatsächlich
@PrimaryContactKey
wird im Ergebnis ein Wert pro Beitrag zugewiesen, sodass er folglich den Wert des letzten Beitrags enthält, den der SELECT-Befehl verarbeitet hat.Welcher Beitrag "letzter" ist, wird durch Clustered-Indizes bestimmt. Wenn kein Clustered-Index verwendet wird oder der Primärschlüssel geclustert wird, ist der "letzte" Beitrag der zuletzt hinzugefügte Beitrag. Dieses Verhalten kann im schlimmsten Fall jedes Mal geändert werden, wenn die Indizierung der Tabelle geändert wird.
Mit einer SET-SELECT-Anweisung wird Ihre Variable auf gesetzt
null
.2. Das SELECT gibt keine Beiträge zurück
Was passiert bei Verwendung der zweiten Version des Codes, wenn Ihre Auswahl überhaupt kein Ergebnis zurückgibt?
Im Gegensatz zu dem, was Sie vielleicht glauben, wird der Wert der Variablen nicht null sein - er behält seinen vorherigen Wert bei!
Dies liegt daran, dass SQL, wie oben angegeben, der Variablen einmal pro Beitrag einen Wert zuweist. Dies bedeutet, dass mit der Variablen nichts unternommen wird, wenn das Ergebnis keine Beiträge enthält. Die Variable hat also immer noch den Wert, den sie hatte, bevor Sie die Anweisung ausgeführt haben.
Mit der Anweisung SET-SELECT wird der Wert sein
null
.Siehe auch: SET versus SELECT beim Zuweisen von Variablen?
quelle