Ich versuche, etwas in der Art eines for-each zu erreichen, bei dem ich die IDs einer zurückgegebenen select-Anweisung nehmen und jede davon verwenden möchte.
DECLARE @i int
DECLARE @PractitionerId int
DECLARE @numrows int
DECLARE @Practitioner TABLE (
idx smallint Primary Key IDENTITY(1,1)
, PractitionerId int
)
INSERT @Practitioner
SELECT distinct PractitionerId FROM Practitioner
SET @i = 1
SET @numrows = (SELECT COUNT(*) FROM Practitioner)
IF @numrows > 0
WHILE (@i <= (SELECT MAX(idx) FROM Practitioner))
BEGIN
SET @PractitionerId = (SELECT PractitionerId FROM @Practitioner WHERE idx = @i)
--Do something with Id here
PRINT @PractitionerId
SET @i = @i + 1
END
Im Moment habe ich etwas, das so aussieht wie oben, aber ich bekomme den Fehler:
Ungültiger Spaltenname "idx".
Könnte jemand
Sie möchten eine CURSOR
verwenden. In den meisten Fällen ist es am besten, eine satzbasierte Lösung zu verwenden. Manchmal ist jedoch eine CURSOR
die beste Lösung. Ohne mehr über Ihr eigentliches Problem zu wissen, können wir Ihnen nicht weiter helfen:
DECLARE @PractitionerId int
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT DISTINCT PractitionerId
FROM Practitioner
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @PractitionerId
WHILE @@FETCH_STATUS = 0
BEGIN
--Do something with Id here
PRINT @PractitionerId
FETCH NEXT FROM MY_CURSOR INTO @PractitionerId
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
Nehmen wir an, die Spalte PractitionerId ist eindeutig, dann können Sie die folgende Schleife verwenden
DECLARE @PractitionerId int = 0
WHILE(1 = 1)
BEGIN
SELECT @PractitionerId = MIN(PractitionerId)
FROM dbo.Practitioner WHERE PractitionerId > @PractitionerId
IF @PractitionerId IS NULL BREAK
SELECT @PractitionerId
END
Ihr select count und select max sollte von Ihrer Tabellenvariablen statt von der tatsächlichen Tabelle sein
DECLARE @i int
DECLARE @PractitionerId int
DECLARE @numrows int
DECLARE @Practitioner TABLE (
idx smallint Primary Key IDENTITY(1,1)
, PractitionerId int
)
INSERT @Practitioner
SELECT distinct PractitionerId FROM Practitioner
SET @i = 1
SET @numrows = (SELECT COUNT(*) FROM @Practitioner)
IF @numrows > 0
WHILE (@i <= (SELECT MAX(idx) FROM @Practitioner))
BEGIN
SET @PractitionerId = (SELECT PractitionerId FROM @Practitioner WHERE idx = @i)
--Do something with Id here
PRINT @PractitionerId
SET @i = @i + 1
END
Ich würde sagen, dass wahrscheinlich alles funktioniert, außer dass die Spalte idx
in der Tabelle, aus der Sie auswählen, nicht wirklich existiert. Vielleicht wollten Sie aus @Practitioner
auswählen:
WHILE (@i <= (SELECT MAX(idx) FROM @Practitioner))
weil das im obigen Code so definiert ist:
DECLARE @Practitioner TABLE (
idx smallint Primary Key IDENTITY(1,1)
, PractitionerId int
)
Die folgende Zeile ist in Ihrer Version falsch:
WHILE (@i <= (SELECT MAX(idx) FROM @Practitioner))
(Fehlt das @)
Es könnte eine Idee sein, Ihre Namenskonvention so zu ändern, dass die Tabellen unterschiedlicher sind.
Obwohl Cursor in der Regel als schreckliches Übel betrachtet werden, glaube ich, dass dies ein Fall für den FAST_FORWARD-Cursor ist - der nächste Schritt in TSQL.
Dies funktioniert in der Regel besser als ein Cursor (fast immer) und ist einfacher:
DECLARE @PractitionerList TABLE(PracticionerID INT)
DECLARE @PractitionerID INT
INSERT @PractitionerList(PracticionerID)
SELECT PracticionerID
FROM Practitioner
WHILE(1 = 1)
BEGIN
SET @PracticionerID = NULL
SELECT TOP(1) @PracticionerID = PracticionerID
FROM @PractitionerList
IF @PracticionerID IS NULL
BREAK
PRINT 'DO STUFF'
DELETE TOP(1) FROM @PractitionerList
END
Ich habe mir einen sehr effektiven, (ich denke) lesbaren Weg dazu ausgedacht.
1. create a temp table and put the records you want to iterate in there
2. use WHILE @@ROWCOUNT <> 0 to do the iterating
3. to get one row at a time do, SELECT TOP 1 <fieldnames>
b. save the unique ID for that row in a variable
4. Do Stuff, then delete the row from the temp table based on the ID saved at step 3b.
Hier ist der Code. Es tut mir leid, es verwendet meine Variablennamen anstelle der in der Frage.
declare @tempPFRunStops TABLE (ProformaRunStopsID int,ProformaRunMasterID int, CompanyLocationID int, StopSequence int );
INSERT @tempPFRunStops (ProformaRunStopsID,ProformaRunMasterID, CompanyLocationID, StopSequence)
SELECT ProformaRunStopsID, ProformaRunMasterID, CompanyLocationID, StopSequence from ProformaRunStops
WHERE ProformaRunMasterID IN ( SELECT ProformaRunMasterID FROM ProformaRunMaster WHERE ProformaId = 15 )
-- SELECT * FROM @tempPFRunStops
WHILE @@ROWCOUNT <> 0 -- << I dont know how this works
BEGIN
SELECT TOP 1 * FROM @tempPFRunStops
-- I could have put the unique ID into a variable here
SELECT 'Ha' -- Do Stuff
DELETE @tempPFRunStops WHERE ProformaRunStopsID = (SELECT TOP 1 ProformaRunStopsID FROM @tempPFRunStops)
END
Hier ist die bessere Lösung.
DECLARE @i int
DECLARE @curren_val int
DECLARE @numrows int
create table #Practitioner (idx int IDENTITY(1,1), PractitionerId int)
INSERT INTO #Practitioner (PractitionerId) values (10),(20),(30)
SET @i = 1
SET @numrows = (SELECT COUNT(*) FROM #Practitioner)
IF @numrows > 0
WHILE (@i <= (SELECT MAX(idx) FROM #Practitioner))
BEGIN
SET @curren_val = (SELECT PractitionerId FROM #Practitioner WHERE idx = @i)
--Do something with Id here
PRINT @curren_val
SET @i = @i + 1
END
Hier habe ich einige Werte in der Tabelle hinzugefügt, weil es anfangs leer ist.
Wir können auf alles zugreifen oder wir können alles im Rumpf der Schleife tun und wir können auf das idx zugreifen, indem wir es in der Tabellendefinition definieren.
BEGIN
SET @curren_val = (SELECT PractitionerId FROM #Practitioner WHERE idx = @i)
--Do something with Id here
PRINT @curren_val
SET @i = @i + 1
END