Streszczenie
Artykuł ten chciałbym poświęcić klauzuli WHERE. Ponieważ do tej pory traktowaliśmy ją bardzo ogólnikowo, myślę, że przyszedł czas na dokładne przeanalizowanie możliwości, których może nam dostarczyć skuteczne jej wykorzystanie.
Treść
Klauzula WHERE służy do ograniczenia zbioru danych, na których przeprowadzana będzie operacja. Dotyczy to zarówno operacji SELECT, jak i UPDATE i DELETE. W warunkach wyszukiwania można uwzględnić szereg operatorów porównania, dopasowywania łańcuchów znaków i wartości niezdefiniowanej NULL. Sama składnia ograniczająca warunki wyszukiwania jest dość prosta:
WHERE | warunki_wyszukiwania |
Podstawowy sposób filtracji danych polega na pobieraniu wartości większy, mniejszy lub równy i porównaniu z pewną wartością, którą podajemy. Przykładem może być wybranie kontaktu z osobami o imieniu Marcin lub ludzi urodzonych po roku 1980. Wszystkie te operacje można bez problemu wykonać za pomocą operatorów porównania. Poniższa tabela przedstawia operatory porównania dostępne w standardzie Transact-SQL.
= |
Równy |
> |
Większy |
< |
Mniejszy |
>= |
Większy, równy |
<= |
Mniejszy, równy |
<> |
Różny |
Przejdźmy teraz do przeanalizowania prostego zapytania, które już wielokrotnie przetoczyło się przez ten kurs. Wygenerujmy sobie w Query Designer skrypt wylistowujący kontakty do osób mających nazwisko Diaz. Poprawnie wygenerowane zapytanie powinno wyglądać w następująco:
SELECT Person.Contact.*
FROM Person.Contact
WHERE (LastName =
N'Diaz')
Skupmy się jednak na klauzuli WHERE. Kolumna LastName jest typu znakowego, z tego względu tekst wpisany do designera jest standardowo konwertowany do łańcuch znakowy. W tym celu SQL Server zastosował funkcję konwersji:
N' wartość_do_konwersji ’
Sprawdźmy, co się stanie, jeśli kolumna, po której będziemy wyszukiwać, będzie miała wartość integer (całkowitoliczbową).
SELECT Person.Contact.*
FROM Person.Contact
WHERE (ContactID = 257)
Ponieważ kolumna ContactID
jest typu całkowitego designer nie musi, a nawet nie może konwertować wartości.
Próba wpisania w kolumnie Filter wyrażenia innego niż cyfra
zakończy się niepowodzeniem i wypisaniem komunikatu o błędzie.
Wiemy już jak wybierać informacje o pojedynczym wierszu. Teraz przejdźmy do
wybrania wszystkich rekordów z bazy, gdzie data modyfikacji wiersza jest
większa niż 2004-07-26. W tym celu przy kolumnie związanej z nakładaniem
warunków wpisujemy datę 2004-07-26.
SELECT Person.Contact.*
FROM Person.Contact
WHERE
(ModifiedDate > CONVERT(DATETIME, '2004-07-26 00:00:00', 102))
Zapytanie, które dostaliśmy jako wynik naszego ograniczenia, jest dość skomplikowane. Spowodowane jest to tym, iż kolumna, na którą nakładamy warunki jest typu datetime. Podobnie jak w przypadku łańcucha znakowego, designer konwertuje tekst wpisany przez użytkownika do formatu takiego, jaki ma kolumna. Konwersja ta jest jednak znacznie bardziej skomplikowana i używam do niej systemowej funkcji CONVERT. Funkcja ta przyjmuje jako pierwszy argument typ na jaki konwertujemy. Drugim argumentem jest obiekt, którego typ chcemy zmienić, zaś ostatni parametr określa styl podawania daty. W zależności, czy rok oddzielimy od miesiąca myślnikami czy kropkami musimy podać stosowny do tego sposób kodowania. Tabelę określającą odpowiednie formaty zamieściłem poniżej.
Rok w postaci dwóch ostatnich cyfr (yy) |
Rok w postaci czterocyfrowej (yyyy) |
Nazwa standardu |
Format daty |
1 |
101 |
USA |
MM/dd/yy |
2 |
102 |
ANSI |
yy.MM.dd |
3 |
103 |
UK/Francuski |
dd/MM/yy |
4 |
104 |
Niemiecki |
dd.MM.yy |
5 |
105 |
Włoski |
dd-MM-yy |
6 |
106 |
Brak |
dd MM yy |
7 |
107 |
Brak |
MM dd, yy |
10 |
110 |
USA |
MM-dd-yy |
11 |
111 |
Japoński |
yy/MM/dd |
Wiemy już, jak przeszukiwać tabelę po typie całkowitym, znakowym oraz po dacie. Spróbujmy teraz złożyć wszystko to razem i zapisać zapytanie wybierające wszystkie kontakty, które zostały zmodyfikowane po 21 lipca 2004 dla osób z nazwiskiem Diaz lub tą, która ma identyfikator równy 13365. Takiego zapytania jeszcze nie pisaliśmy. Mamy tu do czynienia z dwoma różnymi operatorami logicznymi pomiędzy poszczególnymi warunkami AND, OR. Pierwszą operacją jest wybranie z tabeli pól, jakie będą nam potrzebne, czyli LastName, ModificationDate i ContactID. Jeśli mamy już wybrane pola przechodzimy do określania warunków. Zacznijmy od wyznaczenia zbioru rekordów, które zostały zmodyfikowane po 2004-07-21. Czyli w kolumnie Filter wpisujemy naszą datę poprzedzoną znakiem >. Teraz dokładamy warunek ograniczający zbiór rekordów do osób z nazwiskiem Diaz. Na tą chwilę zapytanie wygląda następująco:
SELECT Person.Contact.*
FROM Person.Contact
WHERE (ModifiedDate > CONVERT(DATETIME, '2004-07- 21
00:00:00', 102)) AND (LastName = N'Diaz')
Teraz musimy dodać warunek, który dołoży do naszego zbioru rozwiązań kontakt z identyfikatorem 13365. W tym celu do klauzuli WHERE dodajemy:
OR
(ContactID = 13365)
Całe zapytanie wygląda tak:
SELECT LastName, ModifiedDate, ContactID
FROM Person.Contact
WHERE (ModifiedDate > CONVERT(DATETIME, '2004-07-21
00:00:00', 102)) AND (LastName = N'Diaz') OR (ContactID = 13365)
Jednak przeważnie podczas wyszukiwania nie znamy całego nazwiska lub imienia (albo po prostu nie chce nam się całego wpisywać) wtedy musimy nieco zmodyfikować nasze zapytanie. Jeśli chcielibyśmy wyświetlić listę osób, których imię zaczyna się na literę A zaś nazwisko na S powinniśmy użyć słowo kluczowe LIKE. Składnia wyrażenia jest następująca:
WHERE nazwa_kolumny [NOT] LIKE ‘szukane_tekst’
a zapytanie wygląda w następujący sposób:
SELECT FirstName, LastName
FROM Person.Contact
WHERE (FirstName LIKE N'A%') AND (LastName LIKE N'S%')
Znak % jest znakiem autouzupełnienia. Mówi o tym, że po naszej literze może występować dowolny ciąg różnych znaków. Gdybyśmy przed literą A dodali znak % oznaczałoby to, że szukamy takich imion, które posiadają literę A nie zważając na pozycję na której ona występuje. Lista innych znaków autouzupełnienia przedstawia poniższa tabela.
% |
Zero lub więcej znaków |
_ |
Pojedynczy znak |
[] |
Znak z podanego zakresu |
[^] |
Znak który nie należy do podanego zakresu |
Jeśli chcielibyśmy znaleźć osobę, której nazwisko zaczyna się na literę D, po niej występują dwie inne litery, następnie litera Z i ciąg innych liter musielibyśmy uruchomić następujący skrypt.
SELECT FirstName, LastName
FROM Person.Contact
WHERE
(LastName LIKE N'D__Z%')
Podsumowanie
W powyższym artykule dowiedzieliśmy się, jak w sposób efektywny ograniczać zbiór danych wynikowych ze względu na nasze potrzeby. Wszystkie skrypty, które utworzyliśmy były przedstawione na podstawie operacji SELECT jednak można bez żadnych przeszkód użyć ich zarówno w operacjach UPDATE jak i DELETE. Składnia klauzuli WHERE jest we wszystkich przypadkach taka sama.