O czym?
Jak wybrać n rekordów z tabeli, czyli do czego można użyć ROWNUM. W tym poście pokażę również na jakie problemy możemy napotkać korzystając z ROWNUM.
ROWNUM
Pseudokolumna ROWNUM służy do numerowania rekordów w wyniku działania zapytania – jej wartość rośnie o 1 dla każdego wiersza zwróconego w procesie selekcji rekordów.
SELECT ROWNUM, e.* FROM employees e;
Powyższy przykład powoduje wyświetlenie wszystkich kolumn z tabeli employees. Jako pierwsze zostanie wyświetlona pseudokolumna ROWNUM, która ponumeruje rekordy oraz wyświetlone zostaną pozostałe kolumny z tabeli employees.
W celu wyświetlenia 5 rekordów z tabeli należy użyć warunku WHERE.
SELECT ROWNUM, e.* FROM employees e WHERE ROWNUM<=5;
Powyższy przykład spowoduje wyświetlenie 5 pierwszych rekordów zwróconych przez zapytanie:
SELECT ROWNUM, e.* FROM employees e;
Problemy z ROWNUM
Skoro nie mamy ORDER BY nie wiemy w jakiej kolejności rekordy zostaną wyświetlone. Dodajmy zatem ORDER BY do zapytania, w którym znajduje się ROWNUM:
SELECT ROWNUM, e.* FROM employees e ORDER BY last_name, first_name;
Okazuje się, że rekordy są posortowane z naszym życzeniem – niestety w kolumnie ROWNUM wartości nie są uporządkowane. Dlaczego? Najpierw nastąpiło przypisanie wartości w ROWNUM dla kolejnych rekordów, a dopiero później sortowanie. Możliwe jest obejście tego problemu przy użyciu mechanizmu podzapytań.
Czy to koniec problemów z ROWNUM? Otóż nie. Spróbujmy wybrać drugi rekord z tabeli employees (pomijając „problematyczny” ORDER BY):
SELECT ROWNUM, e.* FROM employees e WHERE ROWNUM=2;
Czemu zapytanie nie wybiera rekordów skoro jeszcze przed chwilą zwracało ich zdecydowanie więcej niż 2? Najpierw następuje przypisanie ROWNUM i sprawdzany jest warunek – czyli dla pierwszego rekordu sprawdzany jest WHERE ROWNUM 1=2. Prawda? Nie. Rekord odrzucamy.
Dla drugiego rekordu zostaje przypisana wartość ROWNUM. Jaka? Otóż wartość 1 – ponieważ poprzedni rekord został odrzucony – jest to pierwszy rekord, który może być w wyniku działania zapytania. Sprawdzamy zatem znany nam warunek WHERE ROWNUM 1=2. Prawda? Nie. Rekord odrzucamy. Itd. Itd. Ten problem można obejść również wykorzystując podzapytania.
Z tej samej przyczyny zapytania WHERE ROWNUM>liczba nie będą wyświetlały rekordów.
Czy w takim wypadku poniższe zapytanie wyświetli rekord/rekordy:
SELECT ROWNUM,e.* FROM employees e WHERE ROWNUM=1;
Wyświetli 1 rekord, ponieważ spełniony będzie warunek WHERE 1=1. Każdy kolejny rekord(kandydat do wyświetlenia) nie zostanie wyświetlony, ponieważ warunek postać WHERE 2=1 (dla drugiego rekordu i każdego kolejnego).
Wnioski:
– Limitowanie działa poprawnie tylko bez wykorzystania klauzuli ORDER BY
– Limitowanie rekordów z wykorzystaniem ROWNUM z użyciem operatora równości jest problematyczne
Rozwiązanie tych problemów przy pomocy podzapytań przedstawię w kolejnym wpisie.