Spis treści:

Kategoria:SQL Server


Jak sprawdzić, czy rekord w tabeli istnieje

Sposób polegający na policzeniu rekordów

Od razu zaznaczam, że jest to sposób zły i nie powinno się go stosować w celu sprawdzenia, czy rekord spełniający określone warunki istnieje. Metoda jest przedstawiona bardziej w celach informacyjnych, a służyć ma jako antywzorzec, antyprzykład. Zanim wyjaśnię, dlaczego metoda jest wręcz ekstremalnie zła, popatrzmy na przykład:

SELECT COUNT(*) FROM Tabela WHERE Kolumna=500

Zastanówmy się, co SQL Server (tak poważniej mówiąc to chyba każdy serwer baz danych) musi zrobić, aby wykonać powyższą instrukcję. Wniosek może być tylko jeden: musi przejrzeć całą tabelę. Oczywiście może posłużyć się indeksami i w pewnym stopniu ograniczyć zakres przeglądanych rekordów, ale nie ma żadnej możliwości, aby przerwać wyliczenia przed czasem. Proste ludzkie rozumowanie podpowiada, że poszukiwania powinno się przerwać po napotkaniu pierwszego elementu spełniającego warunki. Jeżeli szukamy odpowiedzi na pytanie: "czy istnieje?", to już znalezienie jednego daje nam pewną i niepodważalną odpowiedź. Nie ma znaczenia, czy rekord jest jeden, dwa, czy tysiąc - jakiś istnieje. SQL Server liczy do końca, bo zgodnie z zapytaniem chcemy znać dokładną liczbę wystąpień. To proste rozumowanie nie jest jednak dla wszystkich oczywiste i dość często spotyka się przypadki takiej właśnie weryfikacji, czy dany rekord istnieje. Powtórzmy sobie - jest to sposób zły.

Wykorzystanie słowa kluczowego TOP

Powyższe rozważania doprowadzają nas do innej metody. Różnica polega na tym, że przerywamy poszukiwania już wtedy, gdy znajdziemy pierwszy rekord. Przykład takiej techniki pokazany jest poniżej:

SELECT TOP 1 * FROM Tabela WHERE Kolumna=500
--wersja z kolumną
SELECT TOP 1 JakasKolumna FROM Tabela WHERE Kolumna=500

Interpretacja rezultatów jest następująca: jeżeli zapytanie zwróci nam jeden rekord, wtedy mamy pewność, że przynajmniej jeden rekord spełniający podane kryterium istnieje. Jeżeli zapytanie nie zwróci rekordów, to będzie to oznaczało, że nie ma żadnego rekordu spełniającego podane kryterium. Aby nie zwracać pełnego rekordu można skorzystać z wersji z kolumną i zwrócić najmniejszą spośród kolumn rekordu przekazując do wywołującego zapytanie tylko jedną wartość (a nie tyle wartości ile było kolumn).

Nadzszedł czas, aby przedstawić najbardziej czytelne i przejrzyste rozwiązanie.

Sprawdzenie za pomocą operatora logicznego EXISTS

Operator logiczny EXISTS służy właśnie do sprawdzenia warunku istnienia. Problem w tym, że może on występować tylko w warunku zapytania lub w zwykłym warunku i nie może być bezpośrednio użyty w liście kolumn obszaru SELECT. Jest jednak proste obejście, które pozwala wykorzystać tę metodę w normalnym zapytaniu. Przyjrzyjmy się zapytaniu poniżej:

IF EXISTS (SELECT JakasKolumna FROM Tabela WHERE Kolumna=500)
  SELECT 1
ELSE
  SELECT 0

Powyższa technika łączy instrukcję warunkową IF ... ELSE z operatorym EXISTS. Jeżeli rekord istnieje, zwracane jest 1, jeżeli nie istnieje, zwracane jest 0. Można sobie zwrócić inne wratości, powiedzmy True i False, ale będzie to zależało od konkretnych potrzeb.

W tym miejscu należałoby wspomnieć o jeszcze jednej technice, znacznie upraszczającej zapis. Popatrzmy na ostatni już fragment skryptu:

SELECTWHERE EXISTS (SELECT JakasKolumna FROM Tabela WHERE Kolumna=500)

Wszystkie warunki składni SQL są spełnione, a test sprawdzaący istnienie elementu jest właściwy. Jeżeli warunek EXISTS będzie spełniony, wykonana zostanie instrukcja SELECT 1. Jeżeli warunek EXISTS nie będzie spełniony, instrukcja nie zwróci nic.

Wniosek

Wszystkie metody są skuteczne, ale należy za wszelką cenę unikać tej pierwszej, opierającej swoje działanie na instrukcji COUNT. Jest to zdecydowanie najmniej wydajna metoda. Wydajność pozostałych jest porównywalna. Ja osobiście preferuję tę ostatnią, bo jest krótka i przejrzysta. Co prawda nie zwraca tak ładnie wyników jak chociażby ta z instrukcją warunkową IF ... ELSE, ale nie jest to jakiś wielki problem. W aplikacji klienckiej korzystającej z bezpośrednio z LINQ to SQL, ADO.NET lub innych metod dostępu do danych można bez problemu dokonać konwersji 1=>True, NULL=>False.

Kategoria:SQL Server

, 2013-12-20

Brak komentarzy - bądź pierwszy

Dodaj komentarz
Wyślij
Ostatnie komentarze
Dzieki za rozjasnienie zagadnienia upsert. wlasnie sie ucze programowania :).
Co się stanie gdy spróbuję wyszukać:
SELECT * FROM NV_Airport WHERE Code='SVO'
SELECT * FROM V_Airport WHERE Code=N'SVO'
(odwrotnie są te N-ki)
Będzie konwersja czy nie znajdzie żadnego rekordu?