Stary pies uczy się nowej sztuczki
Mówią, że się nie da, ale czasem da się.
Przytrafiło mi się jakiś czas temu w pracy, że znów - jak za starych, dobrych czasów - piszę dużo kodu SQL. Kod ów działa lepiej lub gorzej, ale ja dziś nie o tym.
Dziś - o formatowaniu.
Szkół jest kilka. W odróżnieniu od takiego, dajmy na to, Pythona, Javy czy C#, gdzie format kodu został zestandaryzowany wieki temu i wszyscy się tego standardu (pi x oko) trzymają, o tyle w przypadku SQL programiści nie mogą się dogadać i każdy ciągnie w swoją stronę.

Pociągnę więc i ja.
Jakiś czas temu odkryłem stronę SQL Style Guide, która pokazuje pewien konkretny styl formatowania zapytań SQL, zaproponowany przez Simona Holywella. Bardziej z nudów i dla hecy niż z przekonania zacząłem przerabiać niektóre ze swoich zapytań na ten właśnie styl - i kliknęło!
Tajemnica polega na tym, że tworzymy rzeki.
Rzeki w tym konkretnym kontekście nie są wprawdzie tak piękne, jak w powyższej piosence - ale jednak są całkiem niebrzydkie.
Przykład:
SELECT tytuł
, autor
, rok_wydania
FROM książki
WHERE tytuł = 'Cyberiada';
Widać? No przecież, że widać. Po słowie kluczowym pojawia się pionowa "rzeka", wszystko na lewym brzegu jest wyrównane do prawej i vice versa.
Weźmy odrobinę bardziej skomplikowany przypadek:
SELECT B.title AS BookTitle
, A.name AS AuthorName
, L.language AS Language
FROM books AS B
INNER JOIN authors AS A
ON B.author_id = A.id
INNER JOIN languages AS L
ON B.language_id = L.id
WHERE A.active = 1
ORDER BY B.title;

Oczywiście czym dłuższe zapytanie, tym trudniej utrzymać "rzekę" w jednym kawałku, dlatego czasem trzeba podjąć decyzję o "złamaniu" rzeki:
WITH UpdatedBooks AS (
SELECT B.id AS BookID
, B.title AS NewTitle
FROM books AS B
INNER JOIN authors AS A
ON B.author_id = A.id
WHERE A.active = 0
AND B.updated_at < DATEADD(year, -1, GETDATE())
UNION ALL
SELECT B.id
, B.title
FROM books AS B
INNER JOIN languages AS L
ON B.language_id = L.id
WHERE L.language = 'English'
AND B.pages > 300
)
UPDATE B
SET B.title = U.NewTitle
FROM books AS B
INNER JOIN UpdatedBooks AS U
ON B.id = U.BookID
WHERE B.title != U.NewTitle;

W ostatnim przykładzie mamy dwie "rzeki": jedna wewnątrz podzapytania CTE, druga na końcu. No i sama linia otwierająca CTE również nie jest częścią "rzeki". Niektórzy idą w skrajność i przesuwają słówko "WITH" żeby "pasowało", ale osobiście uważam powyższy wariant za bardziej czytelny.
WITH UpdatedBooks AS ( -- tu WITH kończy się na wysokości SELECT
SELECT B.id AS BookID
, B.title AS NewTitle
FROM books AS B
...
Gwoli ścisłości, podlinkowana na początku artykułu strona o formatowaniu kodu SQL mówi nie tylko o "rzekach", ale również wielu innych elementach, które jednak postanowiłem zignorować, bo mi się tak podoba.
A Ty, Czytelniku, jak formatujesz swój kod SQL?
Komentarze