Stary pies uczy się nowej sztuczki

krótki URL: /6cMvg

kategorie:Pchełki, Pchełki SQL
tagi:None

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