Wyjaśnienie widoków SQL: tworzenie, używanie i unikanie pułapek wraz z przykładami

  1. Strona główna
  2. Blog
  3. Bazy danych i SQL

Bazy danych i SQL

Wyjaśnienie widoków SQL: Tworzenie, używanie i unikanie pułapek wraz z przykładami

Widok to zapisane zapytanie, którego możesz używać jak tabeli. Dowiedz się, jak go utworzyć, dlaczego widoki zapewniają spójność raportów, co robią, a czego nie wpływają na wydajność, a także pułapek, które je łamią.

8 min czytania
Wyjaśniono widoki SQL: twórz, używaj i unikaj pułapek, z przykładami

Najważniejsze

  • widok to nazwane, przechowywane zapytanie, z którego możesz wybierać jak z tabeli.
  • Widok normalny nie przechowuje żadnych danych, więc zawsze pokazuje aktualne wyniki.
  • Widoki upraszczają złożone zapytania, zapewniają spójność logiki biznesowej i mogą ograniczać dostęp do kolumn.
  • Same w sobie nie przyspieszają zapytania, chociaż widoki zmaterializowane mogą to zrobić.

To samo dwudziestoliniowe zapytanie dotyczące raportu zostało skopiowane do pięciu pulpitów nawigacyjnych, a każda kopia uległa pewnemu przesunięciu. Jeden liczy anulowane zamówienia, a drugi nie. Widoki SQL rozwiązują ten problem, jednorazowo definiując tę ​​logikę w bazie danych pod jasną nazwą.

Każdy poniższy przykład uruchomiliśmy w SQLite 3.50 i pokazane wyniki pochodzą z tego uruchomienia. Widoki to standardowy język SQL, ale szczegóły, takie jak aktualizacja poprzez widok, widoki zmaterializowane i obsługa zależności różnią się w zależności od bazy danych i na to zwracamy uwagę.

Co to jest widok?

Widok to SELECT instrukcja zapisana w bazie danych pod nazwą. Kiedy wysyłasz zapytanie do widoku, baza danych uruchamia zapisane zapytanie. Działa jak tabela do odczytu, ale normalny widok nie przechowuje własnej kopii danych.

Pomyśl o filtrze zapisanym w arkuszu kalkulacyjnym. Filtr nie jest drugą kopią arkusza. Jest to sposób patrzenia na te same dane, który zawsze odzwierciedla najnowsze wartości.

Przykładowe tabele

CREATE TABLE customers (
  id INT PRIMARY KEY, name TEXT, city TEXT, email TEXT, credit_limit INT
);
CREATE TABLE orders (
  id INT PRIMARY KEY, customer_id INT, total INT, status TEXT
);

INSERT INTO customers VALUES
 (1,'Asha','Pune','asha@example.com',50000),
 (2,'Ben','Delhi','ben@example.com',20000),
 (3,'Chitra','Pune','chitra@example.com',80000);

INSERT INTO orders VALUES
 (101,1,1200,'paid'), (102,1,800,'paid'),
 (103,2,300,'pending'), (104,3,2500,'paid');

Utwórz widok

Ten widok podsumowuje zamówienia każdego klienta. Ukrywa łączenie, grupowanie i wyrażenie CASE za jedną prostą nazwą:

CREATE VIEW customer_sales AS
SELECT c.id, c.name, c.city,
       COUNT(o.id) AS orders,
       COALESCE(SUM(CASE WHEN o.status = 'paid' THEN o.total END), 0) AS paid_total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name, c.city;

Teraz każdy może z niego korzystać, nie wiedząc, jak to działa:

SELECT * FROM customer_sales ORDER BY paid_total DESC;

-- 3 | Chitra | Pune  | 1 | 2500
-- 1 | Asha   | Pune  | 2 | 2000
-- 2 | Ben    | Delhi | 1 |    0

SELECT name, paid_total FROM customer_sales WHERE city = 'Pune';

-- Asha   | 2000
-- Chitra | 2500

Ben pojawia się z zerem, ponieważ w widoku używane są LEFT JOIN i COALESCE. Takie decyzje, podejmowane raz w widoku, zapewniają spójność raportów. Aby odświeżyć wiedzę na temat obsługi wartości NULL, zobacz Wartości SQL NULL.

Wyświetlenia są zawsze aktualne

Ponieważ widok normalny uruchamia zapytanie za każdym razem, nowe dane pojawiają się natychmiast. Dodaliśmy płatne zamówienie dla Bena i ponownie zapytaliśmy o widok:

INSERT INTO orders VALUES (105, 2, 900, 'paid');

SELECT name, paid_total FROM customer_sales WHERE name = 'Ben';

-- Ben | 900

Nie było etapu odświeżania ani kopiowania, które umożliwiałyby synchronizację. Jest to kluczowa różnica w stosunku do zapisywania wyników zapytania w osobnej tabeli.

Ukrywanie kolumn

Widoki są często używane do udostępniania tylko tych kolumn, których potrzebuje dana osoba lub aplikacja. Tutaj pominięto adresy e-mail i limity kredytowe:

CREATE VIEW public_customers AS
SELECT id, name, city FROM customers;

-- columns: id, name, city

W bazach danych z uprawnieniami, takich jak PostgreSQL, SQL Server i MySQL, użytkownikowi raportującemu można przyznać dostęp do widoku, ale nie do tabeli źródłowej. SQLite nie ma kont użytkowników, więc mogliśmy pokazać tylko samo ograniczenie kolumny. Traktuj widok jako jedną warstwę ochrony. Wrażliwe dane nadal wymagają odpowiedniej kontroli dostępu, a niektóre bazy danych oferują zabezpieczenia na poziomie wierszy w celu filtrowania wierszy według użytkownika.

Wydajność: widoki nie zwiększają prędkości

Powszechnym mitem jest twierdzenie, że widoki przyspieszają wykonywanie zapytań. Kiedy wykonujesz zapytanie, widok normalny jest zastępowany jego definicją, więc baza danych działa tak samo, jakbyś sam napisał pełne zapytanie. Nasz plan wykonania pokazał, że w ramach zapytania uruchamiane jest łączenie i grupowanie widoku:

EXPLAIN QUERY PLAN SELECT * FROM customer_sales WHERE city = 'Pune';

-- CO-ROUTINE customer_sales
-- SCAN c ...
-- SEARCH o USING AUTOMATIC COVERING INDEX (customer_id=?) LEFT-JOIN
-- USE TEMP B-TREE FOR GROUP BY
-- SCAN customer_sales

Zatem widok wolnego zapytania jest nadal wolnym zapytaniem. Szybkość wynika z indeksów i dobrego projektu zapytań, jak opisano w Optymalizacja zapytań SQL i Wyjaśnienie indeksów SQL. Uważaj także na widoki zbudowane na innych widokach. Warstwy zagnieżdżeń ułatwiają wielokrotne łączenie tego samego dużego stołu bez zauważania.

Zmaterializowane poglądy

Zmaterializowany widok zapisuje swoje wyniki, podobnie jak tabela w pamięci podręcznej. Odczyty są szybkie, ale dane są tak świeże, jak ostatnie odświeżenie.

-- PostgreSQL
CREATE MATERIALIZED VIEW daily_sales AS
SELECT order_date, SUM(total) AS revenue FROM orders GROUP BY order_date;

REFRESH MATERIALIZED VIEW daily_sales;
Funkcja Normalny widok Zmaterializowany pogląd
Przechowuje dane Nie Tak
Świeżość Zawsze aktualne Od ostatniego odświeżenia
Czytaj prędkość To samo co zapytanie Szybko
Koszt przechowywania Żadne Tak
Dobre dla Uproszczenie, spójność Ciężkie raporty i dashboardy

Wsparcie jest zróżnicowane. PostgreSQL i Oracle mają widoki zmaterializowane, a SQL Server oferuje widoki indeksowane z własnymi regułami. Brakuje ich w SQLite i MySQL, dlatego ludzie korzystają z regularnej tabeli podsumowań odświeżanej zgodnie z harmonogramem. W tym artykule nie uruchomiliśmy przykładu PostgreSQL.

Wskazówka: przed utworzeniem widoku zmaterializowanego zdecyduj, jak bardzo nieaktualne mogą być dane. „Odświeżanie co godzinę” musi być akceptowalne dla osób czytających raport, więc powiedz im.

Czy możesz zaktualizować widok?

To zależy od bazy danych i widoku. Prosty widok pojedynczej tabeli, bez grupowania lub DISTINCT, często można zaktualizować w PostgreSQL, MySQL i SQL Server, a zmiana zostaje przeniesiona na tabelę. Widok ze złączeniami lub agregacjami zazwyczaj nie jest możliwy, ponieważ baza danych nie jest w stanie określić, który wiersz należy zmienić.

SQLite w ogóle nie pozwala na bezpośredni zapis do widoków. Nasza próba nie powiodła się:

INSERT INTO customer_sales (name) VALUES ('X');

-- cannot modify customer_sales because it is a view

Niektóre bazy danych obsługują INSTEAD OF wyzwalacze umożliwiające zapis widoku, a wiele oferuje WITH CHECK OPTION, które zatrzymują zapisy, które nie byłyby widoczne w widoku. W praktyce większość zespołów utrzymuje widoki tylko do odczytu i zapisuje je w tabelach.

Zależności i złamania

Widok zależy od tabel, z których czyta. Stworzyliśmy widok na stole, a następnie upuściliśmy tabelę:

CREATE TABLE ghost AS SELECT 1 AS x;
CREATE VIEW v_ghost AS SELECT x FROM ghost;
DROP TABLE ghost;

SELECT * FROM v_ghost;
-- no such table: main.ghost

SQLite pozwolił na upuszczenie i nie powiódł się dopiero później, gdy użyto widoku. Inne bazy danych, takie jak PostgreSQL, nie usuwają tabeli, od której zależy widok, chyba że dodasz CASCADE, co również usunie widok. Tak czy inaczej, zmiana nazwy lub usunięcie kolumny może spowodować uszkodzenie wyświetleń, więc sprawdź to w testach regresyjnych po zmianach schematu.

Istnieje również subtelna pułapka z SELECT * w widoku. Stworzyliśmy CREATE VIEW star AS SELECT * FROM customers, a następnie dodaliśmy kolumnę do tabeli. W SQLite widok pochwycił nową kolumnę. Inne bazy danych, w tym PostgreSQL, rozwijają listę kolumn podczas tworzenia widoku, więc nowe kolumny nie pojawiają się. Więc wymień kolumny jawnie. Dokumentuje widok i wszędzie zachowuje się tak samo.

Zarządzanie widokami

Zadanie Wspólna składnia
Utwórz UTWÓRZ WIDOK nazwę JAKO WYBIERZ...
Wymień CREATE OR REPLACE VIEW (PostgreSQL, MySQL, Oracle)
Zamień w SQL Server UTWÓRZ LUB ZMIEŃ WIDOK
Usuń Nazwa DROP VIEW
Usuń bezpiecznie URUCHOM WIDOK JEŚLI ISTNIEJE nazwa

Upuszczenie widoku powoduje usunięcie tylko zapisanego zapytania. W naszym teście tabela customers po upuszczeniu public_customers nadal zawierała wszystkie trzy wiersze. Zachowaj definicje widoków w kontroli wersji wraz z migracjami, aby zmiany były sprawdzane jak każdy inny kod.

Widok vs CTE vs tabela

Opcja Całe życie Przechowuje dane Najlepsze dla
Zobacz Aż do upadku Nie Wspólna logika używana przez wiele zapytań
CTE Jedno stwierdzenie Nie Organizowanie pojedynczego złożonego zapytania
Zmaterializowany pogląd Aż do upadku Tak Szybki odczyt kosztownych wyników
Stół Aż do upadku Tak Rzeczywiste dane

Typowe błędy

  • Oczekuję zwiększenia prędkości. Widok normalny uruchamia zapytanie za każdym razem.
  • Używanie SELECT * w widokach. Zachowanie różni się w przypadku różnych baz danych w przypadku zmiany tabel.
  • Głębokie zagnieżdżanie. Widoki zbudowane na widokach ukrywają kosztowne połączenia.
  • Korzystanie z funkcji ORDER BY w widoku. Porządek nie jest gwarantowany, gdy wysyłasz zapytanie, więc sortuj w zapytaniu zewnętrznym.
  • Niejasne nazwy. Pomocny jest przedrostek taki jak v_ lub wyraźny rzeczownik taki jak customer_sales.
  • Zapominanie widoków podczas migracji. Testuj je po każdej zmianie schematu.

Podsumowanie

Widoki to prosty sposób na umieszczenie ważnej logiki w bazie danych. Używaj ich, aby zachować spójność raportów i ukryć niepotrzebne kolumny, a nie jako trik zwiększający wydajność. Na początek znajdź zapytanie, które pojawia się w kilku miejscach Twojego kodu, zamień je w widok z wyraźnymi kolumnami i skieruj na nie każdego wywołującego.

Najczęstsze pytania

Co to jest widok w SQL?

Widok to zapisane zapytanie SELECT z nazwą. Wysyłasz zapytanie jak do tabeli, a baza danych za każdym razem uruchamia podstawowe zapytanie, więc wyniki są zawsze aktualne.

Czy widok SQL przechowuje dane?

Widok normalny nie przechowuje danych, tylko zapytanie. Zmaterializowany widok przechowuje wyniki i należy go odświeżać, aby być na bieżąco.

Czy widoki są szybsze niż tabele?

Nie. Widok normalny działa tak samo, jak zapytanie bazowe. Zmaterializowane widoki mogą przyspieszyć odczyt, kosztem przechowywania i świeżości.

Czy możesz wstawić do widoku?

Czasami. Proste widoki jednotabelowe można często aktualizować w PostgreSQL, MySQL i SQL Server. Widoki z połączeniami lub grupowaniem zwykle nie są takie, a SQLite na to nie pozwala.

Co stanie się z widokiem, jeśli tabela zostanie upuszczona?

To zależy od bazy danych. Niektórzy nie chcą porzucić tabeli, gdy widok od niej zależy, podczas gdy inni na to pozwalają, a zapytanie o widok kończy się niepowodzeniem.

Ucz się dalej

Pracuj z Stack Quora

Potrzebujesz pomocy przy testowaniu, WordPressie lub SEO?

Pomagamy zespołom dostarczać lepsze oprogramowanie i rozwijać ich witryny. Powiedz nam, nad czym pracujesz, a my zaproponujemy jasny następny krok.

Czytaj dalej

Więcej poradników na testowanie, sztuczna inteligencja i nowoczesny rozwój

Podobał Ci się ten artykuł? Wybierz temat i przejdź bezpośrednio do naszych najnowszych tutoriali.

Sztuczna inteligencja

Wyjaśnienie halucynacji AI: dlaczego modele językowe tworzą rzeczy i jak je zmniejszyć

Wyjaśniono halucynacje AI: czym są, dlaczego powstają w modelach językowych, typowe typy, jak je zredukować za pomocą uziemień i podpowiedzi oraz pr…

Przeczytaj artykuł →
DevOps

Wyjaśnienie zmiennych środowiskowych: pliki .env, sekrety i konfiguracja wykonana prawidłowo

Zmienne środowiskowe wyjaśnione na przykładach Pythona, które przeprowadziliśmy: ich odczytywanie i ustawianie, dlaczego każda wartość jest ciągiem …

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie ograniczenia szybkości interfejsu API: algorytmy, nagłówki i obsługa błędów 429

Ograniczanie szybkości API wyjaśnione za pomocą przeprowadzonej przez nas symulacji: zasobnik tokenów, stałe okno, przesuwane okno, 429 odpowiedzi, …

Przeczytaj artykuł →
Automatyzacja testów

Wyśmiewanie w Pythonie: unittest.mock, patch i błędy, które sprawiają, że testy kłamią

Wyśmiewanie w Pythonie za pomocą unittest.mock, przetestowane: Mock i zwracana wartość, efekt uboczny, łatanie tam, gdzie używana jest nazwa, specyf…

Przeczytaj artykuł →
Testowanie oprogramowania

Wyjaśnienie zasięgu kodu: pokrycie linii i oddziału oraz co naprawdę oznacza 100%

Wyjaśnienie pokrycia kodu za pomocą prawdziwego pliku cover.py: pokrycie linii, gałęzi i warunków, przeczytanie raportu, dlaczego 100% pokrycia może…

Przeczytaj artykuł →
Bazy danych i SQL

DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

DELETE vs TRUNCATE vs DROP wyjaśnione za pomocą przetestowanego SQL: co każdy usuwa, wycofywanie, wyzwalacze, resetowanie tożsamości, prędkość i czy…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie widoków SQL: tworzenie, używanie i unikanie pułapek wraz z przykładami

Widoki SQL wyjaśnione za pomocą zapytań, które uruchomiliśmy: tworzenie widoku, wyniki na żywo, ukrywanie kolumn, wydajność, widoki z możliwością ak…

Przeczytaj artykuł →
Tworzenie oprogramowania

Interfejs TypeScript a typ: rzeczywiste różnice, testowane za pomocą kompilatora

Interfejs TypeScript a typ, sprawdzony z prawdziwym kompilatorem: co oba mogą zrobić, co tylko jeden, łączenie deklaracji, rozszerzenia a przecięcia…

Przeczytaj artykuł →
Tworzenie oprogramowania

Python *args i **kwargs wyjaśnione: elastyczne funkcje z przejrzystymi przykładami

Python *args i **kwargs wyjaśnione za pomocą uruchomionego przez nas kodu: pakowanie i rozpakowywanie, kolejność parametrów, argumenty zawierające t…

Przeczytaj artykuł →
Tworzenie oprogramowania

Funkcje Lambda w Pythonie: składnia, rzeczywiste zastosowania i kiedy ich nie używać

Funkcje lambda w Pythonie wyjaśnione za pomocą uruchomionego przez nas kodu: składnia, sortowanie za pomocą klucza, mapa i filtr, domknięcia, pułapk…

Przeczytaj artykuł →
Sztuczna inteligencja

Kim są agenci AI? Jak one działają, dzięki prostej pętli agenta, którą możesz uruchomić

Kim są agenci AI? Prosty przewodnik po pętli agenta, narzędziach, pamięci i poręczach, z małą pętlą w Pythonie, którą uruchomiliśmy, prawdziwymi zag…

Przeczytaj artykuł →
DevOps

Monitorowanie a obserwowalność: prawdziwa różnica z logami, wskaźnikami i śladami

Wyjaśnienie monitorowania a obserwowalności: znane i nieznane awarie, dzienniki, metryki i ślady, opis incydentu przy kasie, złote sygnały, OpenTele…

Przeczytaj artykuł →
DevOps

Woluminy platformy Docker a mocowania powiązań: utrwalanie danych kontenera we właściwy sposób

Wyjaśniono woluminy Dockera a montowanie powiązań: dlaczego dane kontenera znikają, nazwane woluminy, montowanie powiązań, tmpfs, przykłady tworzeni…

Przeczytaj artykuł →
Automatyzacja testów

TDD vs BDD: kluczowe różnice, jedna funkcja zbudowana w obie strony i kiedy używać każdej z nich

TDD vs BDD wyjaśnione za pomocą jednej funkcji rabatowej zbudowanej w obie strony: refaktoryzacja czerwono-zielona z uruchomionym przez nas kodem, s…

Przeczytaj artykuł →
Tworzenie oprogramowania

Git merge vs rebase: różnice, przykłady i kiedy czego używać

Git merge vs rebase wyjaśnione na prawdziwym wyniku logu, z tabelą porównawczą, złotą zasadą rebase i bezpiecznym procesem pracy zespołu.

Przeczytaj artykuł →
Tworzenie oprogramowania

Python list comprehension: składnia, przykłady i kiedy jej unikać

Python list comprehension wyjaśnione: składnia, filtrowanie, if-else, zagnieżdżone pętle, zmierzone czasy i sytuacje, w których zwykła pętla for jes…

Przeczytaj artykuł →
Bazy danych i SQL

SQL JOIN – wyjaśnienie z przykładami (Inner, Left, Right, Full)

Zrozum złączenia SQL krok po kroku na przykładowych tabelach i zapytaniach: INNER, LEFT, RIGHT, FULL, CROSS i SELF, plus typowe błędy i wskazówki wy…

Przeczytaj artykuł →