Pętla WHILE
Zdarza się, że w skryptach, które tworzymy mamy potrzebę wykonania jakiegoś fragmentu kodu wielokrotnie. W takich sytuacjach przydaje się pętla WHILE. Pętla ta wykonuje blok kodu dopóki spełniony jest konkretny warunek. Jeżeli warunek nie będzie spełniony, to pętla nie wykona swojego bloku kodu.
Przykładowo, aby wykonać dany kawałek kodu 10 razy, możemy posłużyć się zmienną, która będzie przechowywała wartość licznika, który będzie zwiększany o 1 w każdym obiegu pętli. W momencie, gdy licznik osiągnie wartość 10, pętla zakończy swoje działanie.
DECLARE @counter INT = 1;
WHILE @counter <= 10
BEGIN
-- wyświetlenie aktualnej wartości licznika
PRINT @counter;
-- zwiększenie licznika o 1
SET @counter = @counter + 1;
END
PRINT 'Koniec skryptu'
W powyższym przykładzie pętla zakończy się, kiedy zmienna @counter osiągnie wartość 11.
Instrukcja BREAK
Pętle możemy zakończyć wcześniej, niż wynikałoby to z warunku logicznego. W tym celu służy instrukcja BREAK. Przykład:
DECLARE @counter INT = 1;
WHILE @counter <= 10
BEGIN
IF @counter = 7
BEGIN
PRINT 'Jawny koniec wykonywania pętli'
BREAK -- natychmiastowe zakończenie pętli
END
-- wyświetlenie aktualnej wartości licznika
PRINT @counter;
-- zwiększenie licznika o 1
SET @counter = @counter + 1;
END
PRINT 'Koniec skryptu'
Tym razem pętla przerwie swoje działanie, jeszcze przed wypisaniem wartości 7
Instrukcja CONTINUE
Oprócz natychmiastowego przerwania pętli instrukcją BREAK, mamy również możliwość natychmiastowego przejścia do kolejnej iteracji pętli, za pomocą instrukcji CONTINUE. Jednak korzystając z CONTINUE oraz wartości licznika, musimy pamiętać o tym, aby zwiększyć wartość licznika o 1, w przeciwnym wypadku pętla będzie nieskończona.
DECLARE @counter INT = 1;
WHILE @counter <= 10
BEGIN
IF @counter % 2 = 0
BEGIN
PRINT 'Pominięcie pętli dla wartości parzystych'
SET @counter = @counter + 1 -- zwiększenie licznika, aby uniknać pętli nieskończonej
CONTINUE
END
IF @counter = 7
BEGIN
PRINT 'Jawny koniec wykonywania pętli'
BREAK -- natychmiastowe zakończenie pętli
END
-- wyświetlenie aktualnej wartości licznika
PRINT @counter;
-- zwiększenie licznika o 1
SET @counter = @counter + 1;
END
PRINT 'Koniec skryptu'
1
Pominiecie petli dla wartosci parzystych
3
Pominiecie petli dla wartosci parzystych
5
Pominiecie petli dla wartosci parzystych
Jawny koniec wykonywania petli
Koniec skryptu
Zadanie praktyczne
Wykorzystując pętle WHILE napisz procedure, która przyjmuje dwa parametry:
-
BookId- identyfikator książki -
NewCopiesCount- liczba nowych kopii książki
Procedura ma zwiększyć liczbę kopii książki, dodając nowe (Condition = 'New') o NewCopiesCount w bazie danych, z tym, że całkowita liczba kopii książki nie może przekroczyć 10.
Przykładowo, dla książki BookId = 1, która aktualnie ma 7 kopii, jeśli procedura zostanie wywołana z parametrami BookId = 1 i NewCopiesCount = 5, to liczba kopii książki powinna zostać zwiększona do 10.
Natomiast jeśli książka ma ponownie 7 kopii i procedura zostanie wywołana z parametrami, BookId = 1, NewCopiesCount = 2, to liczba kopii książki powinna zostać zwiększona do 9.
Dla książek, które mają już 10 kopii lub więcej, procedura nie powinna dodawać nowych kopii.
Całość przetestuj na przykładowych danych, w różnych scenariuszach.
Rozwiązanie
-- ROZWIĄZANIE
CREATE PROCEDURE IncreaseCopies
@BookId INT,
@NewCopiesCount INT
AS
BEGIN
DECLARE @CurrentCopies INT
SELECT @CurrentCopies = COUNT(*)
FROM Copies
WHERE BookId = @BookId
IF @CurrentCopies + @NewCopiesCount > 10
SET @NewCopiesCount = 10 - @CurrentCopies
DECLARE @i INT = 0
WHILE @i < @NewCopiesCount
BEGIN
-- dodatkowe zabezpieczenie
SELECT @CurrentCopies = COUNT(*)
FROM Copies
WHERE BookId = @BookId
IF @CurrentCopies >= 10
BREAK
---------
INSERT INTO Copies (BookId, Condition)
VALUES (@BookId, 'New')
SET @i = @i + 1
END
END