SQL od podstaw · część 22

UNION i widoki: łączenie i ponowne użycie wyników

Porównaj UNION z UNION ALL i zapisz SELECT jako widok. Naucz się rozdzielać definicję zapytania, dane oraz uprawnienia.

Część bazodanowa INF.03

UNION układa wyniki jeden pod drugim

JOIN łączy kolumny pasujących wierszy. UNION składa wiersze dwóch zgodnych wyników w jeden wynik. Oba SELECT muszą mieć tę samą liczbę kolumn w odpowiadającej kolejności oraz typy, które silnik potrafi połączyć. Sens kolumn również musi być zgodny: cena i liczba klientów nie powinny przypadkowo trafić do jednej kolumny tylko dlatego, że są liczbami.

SELECT id, imie FROM klienci WHERE miasto = 'Gdansk'
UNION
SELECT id, imie FROM klienci WHERE id <= 2
ORDER BY id;

Pierwszy SELECT wybiera Alę i O’Neila, drugi Alę i Jana. UNION usuwa powtórzenie całego wiersza (1, Ala), więc wynik zawiera 3 osoby. Do wyniku włączamy id, aby osoby o identycznym imieniu nadal były odrębnymi klientami.

UNION

Usuwa identyczne wiersze z całego łączonego wyniku.

UNION ALL

Zachowuje wszystkie wystąpienia, także powtórzenia. W przykładzie daje 4 wiersze, w tym dwa wystąpienia Ali.

Wypróbuj zapytanie

SQLite — rzeczywisty silnik przeglądarki. MySQL / SQL Server — ograniczona emulacja składni. Wybierz tryb SQLite do natywnego LIKE. Pozostałe tryby nie są rzeczywistymi serwerami. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.

Ładowanie edytora…

Kolejność kolumn i sortowanie

Nazwy kolumn wyniku pochodzą zasadniczo z pierwszego SELECT. Dopasowanie odbywa się według pozycji, nie według podobieństwa aliasów. Umieść końcowe ORDER BY po ostatnim SELECT; bez niego kolejność wierszy nie jest gwarantowana. Średnik kończy całe złożone zapytanie, nie pierwszą jego część.

SELECT id, imie AS osoba FROM klienci WHERE id <= 2
UNION ALL
SELECT id, imie FROM klienci WHERE id >= 4
ORDER BY id;

Wynik: Ala, Jan, Ewa, Adam. UNION ALL jest dobrym wyborem, jeśli powtórzenia mają znaczenie albo zbiory są rozłączne. UNION wykonuje dodatkową pracę usuwania duplikatów. Nie wybieraj ALL tylko ze względu na szybkość, gdy zadanie wymaga unikatowości.

Podstawowa składnia UNION i UNION ALL jest wspólna dla MySQL/MariaDB, SQL Server, Oracle 19c, Access oraz SQLite. Szczegóły konwersji typów i kolacji się różnią. W Access kwerendę UNION tworzysz w widoku SQL. Do pojedynczych gałęzi z limitami i sortowaniem nie przenoś nawiasów między dialektami bez sprawdzenia dokumentacji.

Widok: nazwana definicja zapytania

Zwykły widok przechowuje definicję SELECT, a nie niezależną kopię wszystkich wynikowych rekordów. Ułatwia ponowne użycie zapytania, upraszcza raporty i może ograniczać udostępniane kolumny. Gdy dane źródłowe się zmieniają, kolejny odczyt widoku odzwierciedla te dane zgodnie z regułami transakcji. Widok materializowany lub indeksowany to osobne, zależne od silnika mechanizmy.

CREATE VIEW v_klienci_kontakt AS
SELECT id, imie, miasto FROM klienci;

SELECT id, imie, miasto FROM v_klienci_kontakt ORDER BY id;

Ćwiczenie tworzy widok bez kolumny email. W SQLite możesz wpisać oba polecenia jako pakiet. Kolejne CREATE tego samego obiektu zwróci błąd; użyj Reset bazy albo świadomie usuń tylko ten własny widok poleceniem DROP VIEW v_klienci_kontakt;. Usunięcie widoku nie usuwa danych tabeli klienci.

Różnice tworzenia i używania widoków

ŚrodowiskoPraktyczna uwaga
MySQL / MariaDBCREATE VIEW; zmiana definicji np. CREATE OR REPLACE VIEW. Sprawdź uprawnienia oraz kontekst SQL SECURITY.
SQL ServerCREATE VIEW musi rozpoczynać odpowiedni pakiet. W SSMS oddziel definicję i późniejszy SELECT separatorem GO; GO jest poleceniem klienta, nie samym T-SQL.
Oracle 19cCREATE VIEW oraz CREATE OR REPLACE VIEW; odpowiednie uprawnienia do obiektów źródłowych.
AccessNajprostszy odpowiednik dydaktyczny to zapisana kwerenda SELECT, np. qKlienciKontakt, wykorzystywana potem przez formularz lub raport.
SQLite w kursieCREATE VIEW i DROP VIEW w izolowanej bazie. Zwykłe widoki są tylko do odczytu bez specjalnych mechanizmów, których edytor nie udostępnia.

Nie dodawaj ORDER BY do definicji z myślą, że każde użycie widoku będzie automatycznie uporządkowane. Sortuj w zapytaniu, które zwraca końcowy raport. Nie zakładaj też, że każdy widok można aktualizować: złączenia, agregacje, DISTINCT i inne elementy ograniczają aktualizowalność zależnie od silnika.

Widok bez email sam nie zabezpiecza tabeli, jeśli ten sam użytkownik nadal ma SELECT na całej tabeli klienci. Ochronę daje właściwa kombinacja widoku i uprawnień. Będzie o tym osobna lekcja. W edytorze nie ma użytkowników ani serwerowych uprawnień.

Ćwiczenia

  1. Porównaj liczbę wierszy pierwszego przykładu z UNION i UNION ALL.
  2. Utwórz własny widok v_tanie_produkty dla cen poniżej 100, potem odczytaj go po cenie rosnąco.
  3. Wyjaśnij, czy DROP VIEW usuwa produkty i czy sam widok stanowi kopię zapasową.
Rozwiązania
CREATE VIEW v_tanie_produkty AS
SELECT id, nazwa, cena FROM produkty WHERE cena < 100;
SELECT nazwa, cena FROM v_tanie_produkty ORDER BY cena, id;

1. 3 i 4 wiersze. 2. Kabel 25, Mysz 60. SQL Server: wykonaj CREATE VIEW osobno, a SELECT w następnym pakiecie. Access: zapisz sam SELECT jako kwerendę. 3. DROP VIEW usuwa definicję widoku, nie źródłowe rekordy. Zwykły widok nie jest backupem.

Źródła: UNION, SQL Server CREATE VIEW, MySQL CREATE VIEW, Access UNION. Rozszerzenie praktyki INF.03.4: łączenie wyników i ponowne użycie zapytań. Dalej: UPDATE i DELETE.

Przewijanie do góry