Transact-SQL (T-SQL)

Transact-SQL (T-SQL) jest głównym językiem służącym do zarządzania i manipulowania danymi w relacyjnym silniku bazy danych (RDBMS) Microsoft SQL Server oraz rozwiązań relacyjnych w chmurze Microsoft Windows Azure. SQL Server wspiera również użycie innych języków zarządzalnych jak microsoft Visual C#, VB lecz T-SQL jest językiem preferowanym. T-SQL jest dialektem standardu jakim jest SQL. SQL jest standardem ISO (International Organization for Standards) i ANSI (American National Standards Institute). Oba te standardy dla SQL są takie same. Ewoluowały one z biegiem czasu, najważniejsze ze zmian to:

  • SQL-86
  • SQL-89
  • SQL-92
  • SQL:1999
  • SQL:2003
  • SQL:2006
  • SQL:2008
  • SQL:2011

Wiodący producenci baz danych, w tym również Microsoft, implementują dialekty języka SQL dla zarządzania i manipulacji danymi dla ich platform bazodanowych. Dlatego jądro języka wygląda tak samo. Jednakże każdy producent decyduje które elementy języka zaimplementować a które nie. Czasami standardy pozostawiają pewne aspekty jako możliwe do zaimplementowania wg własnych potrzeb. Każdy producent tworzy również rozszerzenia języka SQL, kiedy standard nie zapewnia odpowiednich rozwiązań. Pisanie kodu SQL wg standardów jest zalecaną praktyką. Dzięki temu pisany kod jest przenośny i może być używany w różnych silnikach baz danych. Niestandardowe rozwiązania powinny być rozważane tylko wtedy, gdy posiadają one ważne korzyści lub nie mają standardowej alternatywy. Jako przykład można podać operator nierówności, standardem jest forma "<>", lecz T-SQL dopuszcza również używania niestandardowego !=.  Standard SQL jest oparty na modelu relacyjnym, który jest modelem matematycznym służącym do zarządzania i manipulacji danymi. Model relacyjny został stworzony przez Edgara F. Codd'a w 1969r. Od wtedy jest rozwijany przez Chris'a Date, Hugh'a Darwen i innych. powszechnym błędem jest stwierdzenie, że nazwa "relacyjny" wywodzi się od relacji pomiędzy tabelami (klucze główne i obce). Prawdziwym źródłem nazwy modelu relacyjnego jest matematyczny model relacyjny. Relacją w modelu relacyjnym jest to co w SQL'u nazywamy tabelą. Każda relacja posiada nagłówek i ciało. Nagłówkiem jest zbiór atrybutów reprezentowanych w SQL przez kolumny. Atrybuty są identyfikowane przez nazwę i nazwę typu. Ciało relacji składa się ze zbioru krotek które w SQL'u są reprezentowane jako wiersze. Nagłówek każdej krotki jest nagłówkiem relacji. Każda wartość każdego atrybutu krotki jest określonego typu. Najważniejszymi rzeczami które trzeba zrozumieć w T-SQL są pochodząca z modelu relacyjnego podstawy: teoria zbiorów i logika predykatów. Istnieje wiele podstawowych definicji które mają bezpośrednie odzwierciedlenie w kodowanie T-SQL.

  • Term całość. Zbiór powinien być rozważany jako całość. Oznacza to, że nie powinno się pracować z pojedynczymi elementami zbioru lecz ze zbiorem jako całość.
  • Term distinct - zbiór nie ma duplikatów. Np. zbiór {a,b,c} jest równoważny zbiorowi {a,a,b,c,c,c}.
  • Zbiór nie ma określonej kolejności. Zbiór {a,b,c} jest równoważny zbiorowi {b,c,c,a,a}.

Inną gałęzią matematyki na której opiera się model relacyjny jest logika predykatów. Predykat jest wyrażeniem które jest wyliczane dla pewnego obiektu i daje w wyniku wartość TRUE lub FALSE. Np. wyrażenie "zarobki większe niż $50000" jest predykatem. jeżeli przeliczysz predykat dl pracownika który zarabia $60000, to w wyniku otrzymasz TRUE. Model relacyjny używa predykatów jako jednego z elementów jądra. Używa predykatów do filtrowania danych, modelowania modelu, wymuszania integralności itp.

Używanie T-SQL w sposób relacyjny

Jak już zostało wcześniej wspomniane, T-SQL jest bazuje na SQL'u, którego to bazą jest model relacyjny. Jest wiele dróg w SQL jak i T-SQL które różnią się od modelu relacyjnego.Lecz język daje wystarczającą ilość narzędzi aby można było używać go w relacyjny sposób i dzięki temu pisać poprawny kod. Ponieważ zbiór relacyjny powinien być rozpatrywany jako całość to pisząc zapytanie w T-SQL powinno się pracować z tabelą jako z całością. powinno się unikać stosowania iteracyjnych metod wykonania jak np. kursorów czy też pętli. Dla ludzi nauczonych programowania strukturalnego, naturalną drogą jest praca z danymi w sposób iteracyjny. Dlatego użycie kursorów i innych iteracyjnych konstrukcji języka T-SQL jest rozwiązaniem które znają. Jednakże poprawną metodą pracy z modelem relacyjnym jest praca na całych zbiorach danych czyli na tabelach a nie na poszczególnych wierszach tabel. Ważnym czynnikiem jest to, że zbiór relacyjny nie ma duplikatów. T-SQL nie wymusza tego ograniczenia. Aby podążać za teorią relacyjności trzeba wymuszać unikalność w tabelach np. za pomocą kluczy głównych lub kluczy unikalnych. Nawet wtedy, gdy tabela nie pozwala na powtarzanie się rekordów to nie znaczy, że rezultat zapytania ich nie zwróci. Rozważmy np. poniższe zapytanie:

USE TSQL2012; SELECT country FROM HR.Employees;

Zapytanie to zwraca atrybut coutry dla tabeli HR.Employees. W modelu relacyjnym operacja relacyjna na relacji zwraca w wyniku relację. W tym wypadku operacja powinna zwrócić zbiór krajów w których znajdują się pracownicy bez duplikatów. jednakże T-SQL nie eliminuje domyślnie duplikatów. Dając taki wynik:

Country --------------- USA USA USA USA UK UK UK USA UK

W rzeczywistości, T-SQL jest oparty na teorii wielozbiorowości bardziej niż na teorii zbiorów. Wielozbiór (multiset, bag lub superset), jest bardzo podobny do zbioru lecz może posiadać duplikaty. Jak wcześniej wspomniano T-SQL posiada narzędzia które umożliwiają używanie go w sposób relacyjny. Przykładem który może być tutaj zastosowany jest klauzula DISTINCT, która eliminuje duplikaty.

SELECT DISTINCT country FROM HR.Employees;

Wynikiem zapytania jest:

Country --------------- UK USA

Innym bardzo ważnym aspektem teorii zbiorów jest brak kolejności elementów. Dlatego wiersze zapisane w tabelach nie mają żadnego logicznego porządku (koncepcyjnie). Z tego powodu kiedy wykonywane jest zapytanie na tabeli i nie jest wyszczególniony porządek w jakim ma zostać zwrócony wynik to zbiór wynikowy może być zbiorem relacyjnym. Dlatego nie powinno się wyszczególniać sortowania w zapytaniach jeżeli nie jest to konieczne. Np rozważmy zapytanie:

SELECT empid, lastname FROM HR.Employees;

Wykonanie tego zapytania zwróci wynik, który wygląda jakby został posortowany wg kolumny lastname.

empid lastname ------ ------------- 5 Buck 8 Cameron 1 Davis 9 Dolgopyatova 2 Funk 7 King 3 Lew 4 Peled 6 Suurs

Lecz nawet gdyby rekordy zostały zwrócone w innej kolejności to wynik zapytania byłby nadal poprawny. SQL Server potrafi wybierać pomiędzy różnymi metodami przetwarzania zapytań, dlatego nie można zagwarantować, że kolejność wyników będzie taka sama przy wielu wykonaniach tego samego zapytania. Np SQL Server może użyć wielu wątków do przetworzenia danych, przeskanować dane wg kolejności zapisu lub przeskanować utworzony indeks. Aby zagwarantować kolejność otrzymanych wyników zapytania T-SQL trzeba użyć klauzuli ORDER BY jak na przykładzie:

SELECT empid, lastname FROM HR.Employees ORDER BY empid;

Rezultat tego zapytania nie jest relacyjny. Otrzymane wyniki są posortowane wg kolumny empid.

empid lastname ------ ------------- 1 Davis 2 Funk 3 Lew 4 Peled 5 Buck 6 Suurs 7 King 8 Cameron 9 Dolgopyatova

Nagłowek relacji jest zbiorem atrybutów identyfikowanych poprzez nazwy i typy. Nie ma kolejności atrybutów. T-SQL posiada kolejność kolumn bazującą na kolejności w definicji tabeli. Gdy wykonujesz zapytanie SELECT *, to w T-SQL masz gwarancję, że kolumny będą uporządkowane wg kolejności w definicji. Można także użyć kolejności kolumny w klauzuli ORDER BY jak poniżej:

SELECT empid, lastname FROM HR.Employees ORDER BY 1;

Pomijając fakt, że ta praktyka jest nierelacyjna, to może również być powodem potencjalnych błędów jeżeli z jakiegoś powodu zmieni się kolejność kolumn w klauzuli SELECT. Rekomendowanym sposobem jest używanie nazw kolumn. Kolejną dewiacją od modelu relacyjnego jest definiowanie kolumn wynikowych bazujących na wyrażeniu bez nadanie im nazw. Przedstawi to poiższy przykład:

SELECT empid, firstname + ' ' + lastname FROM HR.Employees; empid ------ ------------------ 1 Sara Davis 2 Don Funk 3 Judy Lew 4 Yael Peled 5 Sven Buck 6 Paul Suurs 7 Russell King 8 Maria Cameron 9 Zoya Dolgopyatova

W modelu relacyjnym każdy atrybut musi posiadać nazwę. Aby zapytanie było relacyjne trzeba przypisać nazwę lub alias do każdego wynikowego atrybutu, jak np.:

SELECT empid, firstname + ' ' + lastname AS fullname FROM HR.Employees;

T-SQL pozwala również na to aby kilka kolumn w jednym zapytaniu posiadało tę samą nazwę. Gdy łączysz dwie tabele które mają kolumny keykol.

SELECT T1.keycol, T2.keycol ...

Aby rezultat zapytania był relacyjny to każdy atrybut musi mieć przypisaną unikalną nazwę, dlatego trzeba czasem używać aliasów jak w przykładzie:

SELECT T1.keycol AS key1, T2.keycol AS key2 ...

Predykaty logiki matematycznej mogą mieć wartość TRUE lub FALSE, czyli używają logiki dwuwartościowej. Jednakże istnieje możliwość aby w modelu były uwzględnione wartości nieznane (missing). Wartości nieznane mogą być dwóch rodzajów: nieznane ale zastosowane i nieznane i niezastosowane. Przykładem może być numer telefonu pracownika. Wartością brakującą ale stosowaną jest taka, że pracownik ma telefon ale nie chce podać jego numeru. Brakująca wartość i niezastosowana jest wtedy gdy pracownik po prostu nie posiada telefonu. W ten sposób istnieją dwie różne wartości niezidentyfikowane. T-SQL bazujący na standardzie jakim jest SQL implementuje tylko jedną wartość nieznaną zwaną NULL. Prowadzi to do logiki trzy-wartościowej. Jeśli porównywane wartości istnieją to wynikiem ich porównania jest TRUE lub FALSE, natomiast jeżeli przynajmniej jedna z nich nie istnieje to wynikiem jest wartość NULL.

Podsumowanie

  1. T-SQL jest językiem którego bazą są silne podstawy matematyczne. Jest on oparty na standardzie SQL, który jest oparty na modelu relacyjnym. podstawami modelu relacyjnego jest teoria zbiorów i logika predykatów.
  2. Ważne jest aby rozumieć model relacyjny i stosować jego założenia przy pisaniu kodu T-SQL.
  3. Kiedy opisujemy koncepcje w T-SQL to ważne jest aby używać właściwej terminologii która wskazuje na wiedzę.