Menu

Widoki w SQLite: CREATE VIEW, widoki tymczasowe i INSTEAD OF

Jak działają widoki w SQLite: zapisywanie zapytań jako wirtualnych tabel, kiedy używać widoków tymczasowych i dlaczego widoki w SQLite są domyślnie tylko do odczytu.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Widok to zapisane zapytanie

Widok to instrukcja SELECT z nazwą. Gdy go utworzysz, możesz go odpytywać jak tabelę, ale nic nie jest przechowywane. Przy każdym odczycie z widoku SQLite wykonuje zapytanie źródłowe od nowa.

paid_orders wygląda i zachowuje się jak tabela. Ma kolumny, możesz z niego robić SELECT, możesz go łączyć z innymi tabelami. Ale pod spodem każde zapytanie rozwija się do oryginalnego filtra WHERE status = 'paid'.

To cały model myślowy: widok to alias dla zapytania.

Do czego przydają się widoki

Główna korzyść to nazwa. Skomplikowane zapytanie dostaje krótką, opisową nazwę, a reszta kodu pozostaje czytelna:

Bez widoku każdy wywołujący pisałby GROUP BY sam, a każdy z nich mógłby pomylić filtr. Z widokiem agregacja jest zdefiniowana raz. Wywołujący po prostu pytają o customer_totals i dodają na wierzchu dowolne dodatkowe filtry.

Widoki działają też jako granica w stylu uprawnień. Jeśli zapytanie nie powinno ujawniać kolumny password_hash, zbuduj widok, który wybiera wszystko oprócz tej kolumny, i każ kodowi aplikacji korzystać z widoku.

Składnia CREATE VIEW

Pełna forma:

CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name [(column_aliases)] AS
SELECT ...;

Kilka rzeczy, które warto wiedzieć:

  • IF NOT EXISTS po cichu pomija tworzenie, jeśli widok już istnieje.
  • TEMPORARY (albo TEMP) tworzy widok, który znika po zamknięciu połączenia.
  • Aliasy kolumn w nawiasach pozwalają zmienić nazwy kolumn widoku bez ruszania źródłowego SELECT.

Widok udostępnia przyjaźniejsze nazwy (item, dollars) bez zmiany nazw kolumn w tabeli źródłowej.

Zastępowanie i usuwanie widoków

SQLite nie ma CREATE OR REPLACE VIEW ani ALTER VIEW. Aby zmienić definicję widoku, usuń go i utwórz ponownie:

DROP VIEW IF EXISTS active_orders; to bezpieczna forma: nie zgłosi błędu, jeśli widoku nie ma. Usunięcie widoku nigdy nie wpływa na tabele źródłowe; usuwasz tylko zapisane zapytanie.

Widoki tymczasowe

TEMP VIEW istnieje tylko dla bieżącego połączenia z bazą danych. Po zamknięciu połączenia widok znika. Przydaje się podczas doraźnych sesji analitycznych, po których nie chcesz zostawiać definicji:

Widoki tymczasowe pozwalają też przesłonić nazwę zapytania bez utrwalania jej w schemacie, co jest wygodne podczas eksploracji danych.

Widoki są domyślnie tylko do odczytu

To najważniejsza pułapka. Nie możesz bezpośrednio wykonać INSERT, UPDATE ani DELETE przez widok:

sqlite> INSERT INTO paid_orders (customer, amount) VALUES ('Eve', 50);
Runtime error: cannot modify paid_orders because it is a view

Rozwiązaniem są wyzwalacze INSTEAD OF. Piszesz wyzwalacz, który uruchamia się zamiast próby zapisu i tłumaczy ją na prawdziwą operację na tabeli źródłowej:

Widok pozostaje widokiem, ale zapisy do niego mają teraz dokąd trafić. Wyzwalacze omówimy porządnie na następnej stronie.

Brak widoków zmaterializowanych: zrób je sam

Niektóre bazy danych pozwalają zapisać wyniki widoku na dysku i odświeżać je na żądanie. SQLite tego nie potrafi. Każdy odczyt widoku wykonuje zapytanie źródłowe od nowa. Przy większości obciążeń to nie problem: SQLite jest szybki, a planista zapytań dobry. Przy kosztownych agregacjach odpytywanych wiele razy zbuduj prawdziwą tabelę i sam dbaj o jej synchronizację:

Potem odświeżasz pamięć podręczną według harmonogramu albo podpinasz wyzwalacze na orders, żeby była na bieżąco. To ręczna praca, ale w SQLite jedyna możliwość.

Wyświetlanie widoków

Metadane widoków są w sqlite_master razem z tabelami i indeksami:

Kolumna sql zwraca oryginalną instrukcję CREATE VIEW, co przydaje się, gdy nie pamiętasz, co robi dany widok. W CLI .schema view_name wypisuje to samo w czytelniejszej formie.

Kiedy sięgać po widok

Widoki są warte zachodu, gdy:

  • Nietrywialne zapytanie jest używane w trzech lub więcej miejscach. Nazwanie go raz jest lepsze niż kopiowanie.
  • Chcesz udostępnić części aplikacji wyselekcjonowany podzbiór kolumn lub wierszy.
  • Agregacja jest pojęciowo jedną rzeczą (monthly_sales, active_users), którą wywołujący powinni traktować jak rzeczownik.

Odpuść widok, gdy:

  • Zapytanie jest używane dokładnie w jednym miejscu. Wpisz je bezpośrednio.
  • Liczy się wydajność, a zapytanie źródłowe jest kosztowne: płacisz ten koszt przy każdym odczycie. Zamiast tego zapisz wyniki w prawdziwej tabeli.
  • Widok zależy od innego widoku, który zależy od jeszcze innego. SQLite dobrze radzi sobie z zagnieżdżaniem, ale łańcuch trzech czy czterech widoków sprawia, że podczas debugowania trudno śledzić faktyczny SQL.

Dalej: wyzwalacze

Widoki i wyzwalacze często pojawiają się razem: wzorzec INSTEAD OF, który czyni widoki zapisywalnymi, to jeden z głównych powodów istnienia wyzwalaczy. Wyzwalacze przydają się też same w sobie do dzienników audytu, kaskadowych aktualizacji i pilnowania niezmienników. O tym jest następna strona.

Najczęściej zadawane pytania

Czym jest widok w SQLite?

Widok to zapisana instrukcja SELECT, którą możesz odpytywać jak tabelę. Nie przechowuje żadnych danych: przy każdym odczycie SQLite wykonuje zapytanie źródłowe od nowa. Widoki przydają się, żeby raz nazwać złożone zapytanie i używać go wszędzie albo żeby ukryć kolumny, których wywołujący nie powinni widzieć.

Czy w SQLite można wykonać INSERT lub UPDATE przez widok?

Nie bezpośrednio. Widoki w SQLite są tylko do odczytu: INSERT, UPDATE i DELETE na widoku kończą się błędem. Możesz uczynić widok zapisywalnym, dołączając wyzwalacze INSTEAD OF, które tłumaczą zapis na operacje na tabelach źródłowych.

Czy SQLite obsługuje widoki zmaterializowane?

Nie. SQLite ma tylko zwykłe (wirtualne) widoki: zapytanie wykonuje się przy każdym odczycie z widoku. Jeśli potrzebujesz zapamiętanych wyników, utwórz prawdziwą tabelę i odświeżaj ją samodzielnie albo użyj wyzwalacza, żeby synchronizować ją z tabelami źródłowymi.

Jak wyświetlić wszystkie widoki w bazie SQLite?

Odpytaj sqlite_master: SELECT name FROM sqlite_master WHERE type = 'view';. W CLI .schema pokazuje instrukcje CREATE VIEW, a .tables wyświetla widoki razem z tabelami.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ