IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE
{ sql_statement | statement_block } ]
Niby nic dziwnego, tylko dlaczego wykonywała mi się także konstrukcja
IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE IF Boolean_expression
{ sql_statement | statement_block } ]
[ ELSE
{ sql_statement | statement_block } ]
Podobna do instrukcji warunkowej w C++. Przyjrzyjmy się bliżej na poniższym przykładzie
/* 0 */ USE master
/* 1 */ GO
/* 2 */ DECLARE @a TINYINT;
/* 3 */ SET @a = 0;
/* 4 */ IF @a = 1 PRINT 'tak';
/* 5 */ ELSE IF @a = 0 PRINT '?';
/* 6 */ ELSE PRINT 'nie';
Według wzorca, jeżeli mamy więcej, niż jedno polecenie w bloku warunkowym, powinno być ono otoczone BEGIN ... END. W powyższym przykładzie po ELSE (wiersz 5) dalsze polecenia powinny być zamknięte w bloku, aby mogły działać poprawnie. Daleko nie trzeba odbiegać, wystarczy jedna linijka na potwierdzenie
IF 1 = 0 PRINT 'tak'; PRINT 'Poza if';
Wypisze "Poza if", bo polecenia nie zostały ujęte w bloku, drugie wystąpienie PRINT jest poza zasięgiem polecenia warunkowego IF.
Z pomocą przychodzi Nam dopiero analiza planu wykonania. Okazuje się, że wszystko jest w porządku. A raczej nieporządnie zapisane. IF ... ELSE traktowane jest jako jedno polecenie. Zatem
IF Boolean_expression
{ sql_statement | statement_block }
ELSE IF Boolean_expression
{ sql_statement | statement_block }
ELSE
{ sql_statement | statement_block }
zmieniane jest na
IF Boolean_expression
{ sql_statement | statement_block }
ELSE
BEGIN
IF Boolean_expression
{ sql_statement | statement_block }
ELSE
{ sql_statement | statement_block }
END
Aby to potwierdzić wystarczy spojrzeć na poniższe plany zapytania.
-- część wspólna wszystkich zapytań
USE master
GO
DECLARE @var TINYINT;
SET @var = 0;
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0 PRINT 'tak';
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0 PRINT 'tak';
ELSE SELECT 'nie';
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0
BEGIN
IF @var = 0 PRINT 'tak-tak';
END
ELSE
PRINT 'nie';
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0
BEGIN
IF @var = 0 PRINT 'tak-tak';
ELSE SELECT 'tak-nie';
END
ELSE
PRINT 'nie';
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0
BEGIN
IF @var = 0 PRINT 'tak-tak';
ELSE SELECT 'tak-nie';
END
ELSE
BEGIN
IF @var = 1 PRINT 'nie-tak';
END
-- ----------------------------------------------------------------------------------------------------------------
IF @var = 0
BEGIN
IF @var = 0 PRINT 'tak-tak';
ELSE SELECT 'tak-nie';
END
ELSE
BEGIN
IF @var = 1 PRINT 'nie-tak';
ELSE SELECT 'nie-nie';
END
-- ----------------------------------------------------------------------------------------------------------------
/* Utwórzmy dodatkowo procedurę składowaną, żeby lepiej zobrazować to, nastąpi za chwilę */
USE master
GO
CREATE PROCEDURE dbo.test
AS
RETURN 0;
GO
-- --------
IF @var = 0 PRINT 'tak';
ELSE IF @var = 1 EXEC dbo.test;
ELSE SELECT 'nie';
Widzimy potwierdzenie przetworzenia przez serwer instrukcji warunkowej w tle, bez udziału użytkownika. IF ... ELSE traktuje jako jedno polecenie.