Instrukcja SELECT

Instrukcja SELECT służy do wybierania z bazy danych interesujących nas informacji. Instrukcja ta może od razu dokonywać obliczeń, podsumowań, formatować wynik oraz poprzez odpowiednie mechanizmy czerpać informację z wielu tabel znajdujących się nawet na wielu różnych serwerach bazodanowych. Poniżej znajduje się uproszczona składnia instrukcji SELECT:


SELECT [DISTINCT | ALL] { * | lista_wyrażeń}
FROM lista_tabel | instrukcja_select
[WHERE warunek]
[ [START WITH warunek] CONNECT BY warunek]
[GROUP BY lista_wyrażeń
[HAVING warunek]]
[{UNION | UNION ALL | INTERSECT | MINUS} instrukcja_select]
[ORDER BY {wyrażenie | pozycja | alias} [ASC | DESC]]
[FOR UPDATE]
                            

Rozpatrzymy wszystkie mechanizmy, które możemy mieć do dyspozycji używając instrukcji SELECT do wybierania informacji z bazy danych Oracle.


Podstawowa postać instrukcji SELECT

Klauzula SELECT

Instrukcja SELECT służy do wybierania z bazy danych interesujących nas informacji. Instrukcja ta może od razu dokonywać obliczeń, podsumowań, formatować wynik oraz poprzez odpowiednie mechanizmy czerpać informację z wielu tabel znajdujących się nawet na wielu różnych serwerach bazodanowych.

Najprostsza postać instrukcji SELECT wygląda w następujący sposób:


SELECT lista_kolumn
FROM tabela;
                        

tabela jest to nazwa dowolnej tabeli, natomiast lista_kolumn to dowolna ilość kolumn rozdzielonych przecinkami.

Przykład

Wypisać nazwy wszystkich towarów.

SELECT tow_nazwa
FROM towary;
                        

Przykład

Wypisać nazwy wszystkich towarów i ich ceny.

SELECT tow_nazwa, tow_cena
FROM towary;
                        

Przykład

Wypisać adresy klientów poprzedzając je słowem „ADRES”.

SELECT 'ADRES', klt_adres
  FROM klienci;
                        

Jeżeli jakaś kolumna przyjmuje wartość pustą (NULL), to zapytanie zwraca w danym wierszu też wartość pustą.

Przykład

Wypisać imię, nazwisko, nazwę i adres klientów

SELECT klt_imie, klt_nazwisko, klt_nazwa, klt_adres
  FROM klienci;
                        

Aby uniknąć pustych miejsc można użyć wywołania funkcji wbudowanej SQL, która sprawdza, czy wartość jest pusta, i w takim wypadku zastępuje ją wskazaną, inną wartością. Funkcja ta nazywa się NVL, a jej wywołanie ma następującą postać:


nvl(nazwa_kolumny, wartość_zastępcza)
                        

Wartość zastępcza musi być tego samego typu, co badana kolumna.

Przykład

Wypisać imię, nazwisko, nazwę i adres klientów, tak, aby w miejscu wartości pustych pojawiła się stosowna informacja.

SELECT nvl(klt_imie, 'Brak'),
       nvl(klt_nazwisko, 'Brak'),
       nvl(klt_nazwa, 'Brak'),
       klt_adres
  FROM klienci;

                        

Jeżeli chcemy wypisać zawartość wszystkich kolumn z pewnej tabeli, to zamiast wypisywać ich nazwy, można posłużyć się znakiem *.

Przykład

Wypisać wszystkie informacje o towarach.

SELECT *
  FROM towary;
                        

Po klauzuli SELECT może pojawić się wyrażenie zawierające stałe i kolumny tabeli.

Przykład

Wypisać nazwy wszystkich towarów, ich ceny netto i ceny brutto.

SELECT tow_nazwa,
       tow_cena,
       tow_cena * (1 + nvl(tow_podatek, 0)/100)
  FROM towary;
                        

Każda pozycja znajdująca się po klauzuli SELECT może mieć zdefiniowaną dla siebie nazwę, tzw. alias.

Przykład

Wypisać nazwy wszystkich towarów, ich ceny netto i ceny brutto. Kolumnę z ceną netto nazwać „NETTO”, kolumnę z ceną brutto nazwać „BRUTTO”.

SELECT tow_nazwa,
       tow_cena AS netto,
       tow_cena * (1 + nvl(tow_podatek, 0)/100) AS brutto
  FROM towary;
                        

Jeżeli alias zawiera znaki spacji lub ważną rolę odgrywa wielkość liter, to należy go ująć w cudzysłów (podwójny). Słowo kluczowe AS nie jest wymagane przy definiowaniu aliasu.

Przykład

Wypisać nazwy wszystkich towarów, ich ceny netto i ceny brutto. Kolumnę z ceną netto nazwać „cena netto”, kolumnę z ceną brutto nazwać „cena brutto”.

SELECT tow_nazwa,
       tow_cena "cena netto",
       tow_cena * (1 + nvl(tow_podatek, 0)/100) "cena brutto"
  FROM towary;
                        

Jeżeli interesuje nas nie ilość wystąpień pewnej wartości w kolumnie, ale tylko informacja, jakie wartości się w kolumnie pojawiają, możemy umieścić za klauzulą SELECT dodatkową klauzulę DISTINCT.

Przykład

Wyświetlić bez powtórzeń wszystkie typy klientów, jakie występują w tabeli klienci.

SELECT DISTINCT klt_typ
  FROM klienci;
                        

W przypadku, gdy chcemy wypisać bez powtórzeń wartości kilku kolumn, to klauzulę DISTINCT stosujemy tylko raz po klauzuli SELECT. W wyniku otrzymamy nie powtarzające się kombinacje wyspecyfikowanych kolumn i wyrażeń.

Przykład

Wyświetlić bez powtórzeń wszystkie typy klientów i ich imiona.

SELECT DISTINCT klt_typ, klt_imie
  FROM klienci;
                        

Sortowanie

Wiersze zwracane przez zapytanie nie są uporządkowane w żaden sposób, pojawiają się w nieokreślonej kolejności.

Aby uporządkować kolejność wierszy należy zastosować na końcu zapytania klauzulę ORDER BY. Nie należy stosować tej klauzuli niepotrzebnie, gdyż wiąże się ona z dużym dodatkowym nakładem pracy, jaki musi wykonać serwer Oracle w celu wykonania zapytania. Aby posortować wynik zapytania po klauzuli ORDER BY należy dodać nazwę kolumny, według której chcemy posortować wynik zapytania.

Przykład

Wypisać wszystkie informacje o towarach, porządkując je według nazwy.

SELECT *
  FROM towary
 ORDER BY tow_nazwa;
                        

Domyślnie porządek sortowania jest rosnący, można to zmienić wstawiają po nazwie kolumny, według której sortujemy, odpowiednio słowo ASC lub DESC.

Przykład

Wypisać wszystkie informacje o towarach, porządkując je według nazwy malejąco.

SELECT *
  FROM towary
 ORDER BY tow_nazwa DESC;
                        

Zamiast nazwy kolumny po klauzuli ORDER BY może pojawić się wcześniej zdefiniowany alias dla tej kolumny lub dla pewnego wyrażenia..

Przykład

Wypisać nazwy wszystkich towarów, ich ceny netto i ceny brutto. Kolumnę z ceną netto nazwać „NETTO”, kolumnę z ceną brutto nazwać „BRUTTO”. Posortować wynik rosnąco według ceny brutto.

SELECT tow_nazwa,
       tow_cena netto,
       tow_cena * (1 + nvl(tow_podatek, 0)/100) brutto
  FROM towary
 ORDER BY brutto ASC;

                        

Zamiast nazwy kolumny lub aliasu po klauzuli ORDER BY może pojawić się numer określający pozycję składnika z listy składników klauzuli SELECT, według którego ma być posortowany wynik.

Przykład

Wypisać nazwy wszystkich towarów, ich ceny netto i ceny brutto. Nie definiować aliasów. Posortować wynik malejąco według ceny brutto.

SELECT tow_nazwa,
       tow_cena,
       tow_cena * (1 + nvl(tow_podatek, 0)/100)
  FROM towary
 ORDER BY 3 DESC;
                        

Po klauzuli ORDER BY może pojawić się lista kilku kolumn lub wyrażeń lub numerów rozdzielonych przecinkami. W takim wypadku wynik zapytania zostanie posortowany według pierwszej pozycji, następnie w przypadku, gdy pierwsza kolumna jest równa, to podzbiór zostanie posortowany według drugiej pozycji, itd.

Przykład

Wypisać nazwy, ceny netto i podatek wszystkich towarów. Wynik posortować według podatku malejąco, a następnie według ceny rosnąco.

SELECT tow_nazwa,
       tow_cena,
       nvl(tow_podatek, 0)
  FROM towary
 ORDER BY 3 DESC, tow_cena ASC;
                        

W przypadku sortowania w porządku rosnącym wartości puste (NULL) zostają wypisane na końcu, w przypadku sortowania w porządku malejącym wypisane zostają na początku.

Przykład

Wypisać wszystkie informacje o klientach sortując wynik malejąco według imienia.

SELECT *
  FROM klienci
 ORDER BY klt_imie DESC;
                        

Pozycje znajdujące się po klauzuli ORDER BY nie muszą się znajdować na liście pozycji po klauzuli SELECT.

Operatory i priorytety

W instrukcji SELECT mogą wystąpić dowolnie skomplikowane wyrażenia zbudowane z nazw kolumn, wywołań funkcji i ze stałych literałów. Budując różne wyrażenia łączymy poszczególne komponenty przy pomocy operatorów. Poniżej znajduje się opis operatorów dostępnych w Oracle SQL.

Operatory arytmetyczne

+ - * /

Operator konkatenacji

||

Operator ten służy do łączenia dwu wartości tekstowych.

Operatory porównań

> >= = < <= <> != ^=

Operator zakresu

x [NOT] BETWEEN y AND z

Operator ten sprawdza, czy wartość x mieści [nie mieści] się w przedziale domkniętym y,z

Operator przynależności do listy

x [NOT] IN (x1, x2, ..., xn)

Operator ten sprawdza, czy wartość x znajduje [nie znajduje ] się na liście wartości x1, x2, ..., xn.

Operator wzorca

x [NOT] LIKE y

Operator ten sprawdza, czy wartość napisu x przystaje [nie przystaje] do maski y. Podczas definiowania maski możemy korzystać ze znaków specjalnych: „%” zastępuje dowolną ilość dowolnych znaków, natomiast „_” zastępuje dokładnie jeden dowolny znak.

Operator testowania wartości

x IS [NOT] NULL

Operator ten sprawdza, czy x zawiera [nie zawiera] wartości NULL.

Operatory logiczne

NOT AND OR

Wartość NULL i trójstanowa logika Oracle

NOT TRUE FALSE NULL
FALSE TRUE NULL
AND TRUE FALSE NULL
TRUE TRUE FALSE NULL
FALSE FALSE FALSE FALSE
NULL NULL FALSE NULL
OR TRUE FALSE NULL
TRUE TRUE TRUE TRUE
FALSE TRUE FALSE NULL
NULL TRUE NULL NULL

Każde wyrażenie arytmetyczne zawierające choć jeden składnik lub czynnik z wartością pustą produkuje pusty wynik.

Przykład

Wypisać nazwy towarów oraz ceny brutto (bez używania funkcji nvl).

SELECT tow_nazwa,
       tow_cena * (1 + tow_podatek/100)
  FROM towary;
                        

Zasada ta nie obowiązuje w przypadku operatora konkatenacji, kiedy to wartość NULL jest traktowana jako pusty napis o długości zero.

Przykład

Wypisać jako jeden napis imię, nazwisko, nazwę i adres klientów. Całość nazwać „Dane klientów”.

SELECT klt_imie||' '||klt_nazwisko||' '||
       klt_nazwa||' '||klt_adres "Dane klientów"
  FROM klienci;
                        

Również w wyrażeniach logicznych zasada przytoczona na początku tego rozdziału nie zawsze działa. Jeżeli wyrażenie logiczne zawiera wartość pustą i jeżeli pomimo to wynik wyrażenia jest jednoznaczny, to wynik ten jest niepusty.


        NOT 	NULL 	=> 	NULL
TRUE 	AND 	NULL 	=> 	NULL
FALSE 	AND 	NULL 	=> 	FALSE
TRUE 	OR      NULL 	=> 	TRUE
FALSE 	OR      NULL 	=> 	NULL
                        

Priorytety operatorów

Składowe złożonych wyrażeń łączone są ze sobą w kolejności zależnej od priorytetów operatorów. W przypadku operatorów o tym samym priorytecie łączenie następuje od lewej strony do prawej. Domyślną kolejność łączenia można zmienić przy pomocy nawiasów. Poniżej znajdują się operatory uszeregowane w wiersze według priorytetu łączenia, od największego do najmniejszego.


*, /, NOT
+, -, ||
<, <=, =, >=, >, <>, !=, ^=, IS, IN, BETWEEN, LIKE
AND
OR
                        

Nie zostały tu przedstawione wszystkie dostępne w Oracle SQL operatory. Zostaną one wprowadzone i omówione w kolejnych rozdziałach poświęconych instrukcji SELECT.

Selekcja wierszy

Zazwyczaj nie jest potrzebna informacja o wszystkich rekordach znajdujących się w tabeli. W takiej sytuacji możemy do instrukcji SELECT dodać klauzulę WHERE wraz z wyrażeniem logicznym. W wyniku takiego zapytania zwracane są tylko te wiersze, dla których wyrażenie przyjęło wartość prawdziwą.

Przykład

Wyświetlić informacje o klientach indywidualnych.

SELECT *
  FROM klienci
 WHERE klt_typ = 'IND';
                        

Przykład

Wyświetlić informacje o towarach droższych niż 1000 złotych.

SELECT *
  FROM towary
 WHERE tow_cena > 1000;
                        

Przykład

Wypisać opis zamówień złożonych przez klientów o numerach 1002 i 1003.

SELECT zam_opis
  FROM zamowienia
 WHERE zam_klt_id IN (1002, 1003);
                        

Warunek następujący po klauzuli WHERE może być dowolnie skomplikowany

Przykład

Wyświetlić informacje o towarach, które są tańsze niż 1500 i objęte podatkiem 23%.

SELECT *
  FROM towary
 WHERE tow_cena < 1500
   AND tow_podatek = 23;
                        

Przykład

Wyświetlić nazwy i ceny towarów, których nazwa zaczyna się na literę „Z” lub kończy na litery „sz”.

SELECT tow_nazwa, tow_cena
  FROM towary
 WHERE tow_nazwa LIKE ‘Z%’
    OR tow_nazwa LIKE ‘%sz’;
                        

W przypadku, gdy wyrażenie po klauzuli WHERE przyjmuje dla jakiegoś wiersza wartość FALSE lub NULL, to wiersz ten jest odrzucany.

Przykład

Wyświetlić informacje o towarach objętych podatkiem różnym od 22%.

--
-- Niepoprawnie
SELECT *
  FROM towary
 WHERE tow_podatek <> 23;
--
-- Poprawnie
SELECT *
  FROM towary
 WHERE tow_podatek <> 23
    OR tow_podatek IS NULL;
--
-- Poprawnie
SELECT *
  FROM towary
 WHERE nvl(tow_podatek, 0) <> 23;