Przejdź do treści
FullstackDev

Instrukcje warunkowe

Czasem w naszych skryptach SQL będziemy mieli potrzebę wykonać róźne polecenia SQL, w zależności od jakiegoś warunku, lub inaczej mówiąc, będziemy musieli sterować przepływem egzekucji kodu. Taką potrzebę zaspokoi nam instrukcja warunkowa.

Instrukcja warunkowa w T-SQL (Transact-SQL) to mechanizm programowania używany do wykonywania różnych działań w zależności od spełnienia określonych warunków. Najczęściej używaną instrukcją warunkową w T-SQL jest IF, lub jej wersje IF..ELSE, czy nawet bardziej rozbudowane IF..ELSEIF..ELSE.

Instruckja IF

Instrukcja IF w T-SQL służy do sprawdzenia, czy określony warunek jest spełniony. Jeśli warunek jest spełniony, kod wewnątrz bloku BEGIN i END zostanie wykonany. Jeśli warunek nie jest spełniony, kod wewnątrz bloku BEGIN i END zostanie pominięty.

Składnia instrukcji IF wygląda następująco:

IF warunek
BEGIN
    -- Kod do wykonania, jeśli warunek jest spełniony
END

Przykładowo, jeżeli istnieje użytkownik, który jeszcze nie zwrócił książek, to dla takiego użytkownika możemy zaktualizować datę zwrotu wypożyczeń.

W przeciwnym wypadku, czyli jeśli wszystkie książki zostały już zwrócone, blok kodu między BEGIN i END nie zostanie wykonany.

DECLARE @UserId INT;
SELECT TOP 1 @UserId = UserId
FROM Loans
WHERE ReturnDate IS NULL
GROUP BY UserId
ORDER BY COUNT(*) DESC

IF @UserId IS NOT NULL
BEGIN
    PRINT 'Aktualizacja ReturnDate'
    UPDATE Loans
    SET ReturnDate = GETDATE()
    WHERE UserId = @UserId
END

Aktualizacja ReturnDate

Instrukcja IF ELSE

Do instrukcji IF możemy dopisać też blok ELSE, który zostanie wykonany, jeśli warunek w IF nie zostanie spełniony.

IF warunek
BEGIN
    -- Kod do wykonania, jeśli warunek jest spełniony
END
ELSE
BEGIN
    -- Kod do wykonania, jeśli warunek nie jest spełniony
END

Przykładowo, dodanie nowego egzemplarza The Hobbit, lub aktualizacji stanu istniejących w zależności od liczby dostępnych egzemplarzy w bazie danych:

DECLARE @theHobbitId INT = (SELECT BookId FROM Books WHERE Title = 'The Hobbit')
DECLARE @theHobbitCopiesCount INT = (SELECT COUNT(CopyId) FROM Copies WHERE BookId = @theHobbitId)
IF @theHobbitCopiesCount > 5
BEGIN 
    PRINT 'Aktualizacja egzemplarzy'
    UPDATE Copies
    SET Condition = 'Good'
    WHERE BookId = @theHobbitId
END
ELSE 
BEGIN
    PRINT 'Dodawanie nowego egzemplarza'
    INSERT INTO Copies (Condition, BookId)
    VALUES ('Ok', @theHobbitId)
END

Dodawanie nowego egzemplarza

Instrukcja IF ELSE IF ELSE

W przypadku, gdy mamy do czynienia z wieloma warunkami, które chcemy sprawdzić, możemy skorzystać z instrukcji IF ELSE IF ELSE. Instrukcja ta pozwala na sprawdzenie wielu warunków, z których tylko jeden może być spełniony.

Poniższy przykład wyświetli 'Sobota', 'Niedziela' lub 'Inny dzień tygodnia' w zależności od wartości zmiennej dzienTygodnia.

DECLARE @dzienTygodnia INT = 1
IF @dzienTygodnia = 6
BEGIN
    PRINT 'Sobota'
END
ELSE IF @dzienTygodnia = 7
BEGIN
    PRINT 'Niedziela'
END
ELSE
BEGIN
    PRINT 'Inny dzień tygodnia'
END

Tylko jeden z bloków IF, ELSE IF lub ELSE zostanie wykonany. W powyższym przykładzie, jeśli wartość zmiennej dzienTygodnia wynosi 6, zostanie wyświetlony napis 'Sobota'. Jeśli wartość zmiennej wynosi 7, zostanie wyświetlony napis 'Niedziela'. W przeciwnym przypadku zostanie wyświetlony napis 'Inny dzień tygodnia'.

DECLARE @userId INT, @totalLoans INT;
SELECT TOP 1 @userId = UserId, @totalLoans = COUNT(*) 
FROM Loans
GROUP BY UserId
ORDER BY COUNT(*) DESC
SELECT @userId, @totalLoans
IF @totalLoans > 5
BEGIN
    PRINT 'Usuwanie wpisu wypożyczeń'
    DELETE FROM Loans 
    WHERE UserId = @userId AND CopyId IN (SELECT CopyId 
                                          FROM Copies
                                          WHERE Condition != 'Good')
END
ELSE IF @totalLoans > 3
BEGIN
    PRINT 'Aktualizacja stanu egzemplarzy'
    UPDATE Copies
    SET Condition = 'Ok'
    WHERE CopyId IN (SELECT CopyId FROM Loans WHERE UserId = @userId)
END
ELSE
BEGIN
    PRINT 'Dodawanie nowego wypożyczenia'
    DECLARE @leastLoanedCopyId INT = (SELECT TOP 1 CopyId 
                                      FROM Loans
                                      GROUP BY CopyId
                                      ORDER BY COUNT(*))
    INSERT INTO Loans (UserId, CopyId, LoanDate)
    VALUES (@userId, @leastLoanedCopyId, GETDATE())
END

Aktualizacja stanu egzemplarzy

W zależności od złóżoności logiki biznesowej, instrukcję ELSE IF można powielać, aby sprawdzić więcej warunków, a sama instrukcja ELSE nie jest obowiązkowa.

Zadanie

Napisz skrypt, który sprawdzi, czy aktualnie jest więcej książek wypożyczonych, jeszcze nie oddanych, niż tych, które zostały już zwrócone. W zależności od wyniku, skrypt powinien wyświetlić odpowiedni komunikat o ile jest więcej książek zostało już zwrócone lub jeszcze nie.

Przykładowo, jeżeli w bazie było 5 wypożyczonych książek, z czego 3 zostały już zwrócone, a 2 jeszcze nie - to skrypt powinien wyświetlić komunikat "Wypożyczono o 1 więcej książek, które zwrócono".

Aby poprawnie wyświetlić komunikat, to do konwersji zmiennej liczbowej na typ tekstowy użyj funkcji CONVERT(NVARCHAR, @zmiennaTypuInt).

Rozwiązanie
DECLARE @returnedCopiesCount INT, @notReturnedCopiesCount INT;
SET @returnedCopiesCount = (SELECT COUNT(*) FROM Loans WHERE ReturnDate IS NOT NULL)
SET @notReturnedCopiesCount = (SELECT COUNT(*) FROM Loans WHERE ReturnDate IS NULL)
PRINT @returnedCopiesCount
PRINT @notReturnedCopiesCount
IF @returnedCopiesCount > @notReturnedCopiesCount
BEGIN
    DECLARE @difference INT = @returnedCopiesCount - @notReturnedCopiesCount
    PRINT 'Zwrócono o' + CONVERT(NVARCHAR, @difference) + ' więcej niż wypożoczono'
END
ELSE IF @returnedCopiesCount = @notReturnedCopiesCount
BEGIN 
    PRINT 'Zwrócono tyle samo książek, co jeszcze nie zwrócono'
END
ELSE 
BEGIN
    DECLARE @differenceNotReturned INT = @notReturnedCopiesCount - @returnedCopiesCount
    PRINT 'Nie zwrócono o ' + CONVERT(NVARCHAR, @differenceNotReturned) + ' więcej niż do tej pory zwrócono'
END

13

19

Nie zwrócono o6 wiecej niz do tej pory zwrócono