Wprowadzenie
Widok w SQL Server to wirtualna, podobna do tabeli struktura oparta na zestawie wyników instrukcji SQL. Na pozór widok jest podobny do tabeli z sygnaturą struktury wierszy i kolumn. Jednak te wiersze i kolumny pochodzą z tabel, do których odwołuje się zapytanie, które definiuje widok.
Używamy widoków, aby skoncentrować się na betonowych kolumnach do celów, dla których są tworzone. Widoki mogą również służyć ze względów bezpieczeństwa. Odfiltrowują kolumny w tabelach podstawowych, których nie chcesz uwidaczniać niektórym użytkownikom. Widoki filtrują kolumny, takie jak klauzula WHERE filtruje wiersze.
Innym powodem widoków jest prostota. Łączą kolumny z kilku różnych tabel i tworzą ogólny wygląd, który wygląda jak pojedyncza tabela.
Rodzaje widoków
Tworzenie podstawowych widoków zdefiniowanych przez użytkownika jest łatwe. Proces jest podobny do pisania zapytań, które odwołują się do jednej lub więcej tabel.
- Widoki indeksowane to takie, które zostały zmaterializowane lub zapisane w formie tabeli. Widoki indeksowane mogą poprawić wydajność zapytań, które agregują wiele wierszy. Jednak nie są one odpowiednie, jeśli tabele bazowe są często aktualizowane.
- Widoki partycjonowane łączą dane podzielone na partycje poziome z tabel lokalnie (w tej samej instancji) lub w wielu, przy użyciu połączonych serwerów.
- Widoki systemowe to typowe struktury używane przez program SQL Server do ujawniania metadanych wykazu. Widoki systemowe to większość tych struktur, które są zapytaniami o rozwiązywanie problemów z wydajnością lub badanie instancji SQL Server.
Tworzenie widoku z jednej tabeli
Spójrz na przykład z Listingu 1. Pierwsza instrukcja zwraca WSZYSTKIE rekordy w tabeli Purchasing.PurchaseOrders (1a), podczas gdy drugie zapytanie zwraca tylko kilka kolumn (1b).
Korzystając z drugiego zapytania, możemy utworzyć widok, który zwraca ten sam zestaw wyników, co (1b). Kiedy to zrobimy, możemy wysłać zapytanie do View, aby uzyskać żądane dane wyjściowe. W ten sposób upraszczamy zapytanie dla użytkownika końcowego.
-- Listing 1: Creating a Basic User-Defined View
-- 1a
SELECT * FROM
Purchasing.PurchaseOrders;
-- 1b
SELECT
PurchaseOrderID
, SupplierID
, OrderDate
, ExpectedDeliveryDate
FROM Purchasing.PurchaseOrders;
-- 1c
CREATE VIEW Purchasing.QuickOrders
AS
SELECT
PurchaseOrderID
, SupplierID
, OrderDate
, ExpectedDeliveryDate
FROM Purchasing.PurchaseOrders;
-- 1d
SELECT * FROM Purchasing.QuickOrders ;
Tworzenie widoku z dwóch tabel
Używając JOIN, możemy pobrać dane z dwóch lub więcej tabel, które mają relację. Korzystając z widoków, możemy uprościć dostęp do takich danych.
Listing 2 (2a) przedstawia JOIN między Purchasing.PurchaseOrders i Purchasing.PurchaseOrderLines. Możemy utworzyć widok z tego JOIN, co pozwoli nam pobrać te same dane za pomocą zapytania, jak pokazano w (2c).
-- Listing 2: Creating a View from Two Tables
-- 2a
SELECT
po.PurchaseOrderID
, po.SupplierID
, po.OrderDate
, po.ExpectedDeliveryDate
, pol.Description
, pol.ExpectedUnitPricePerOuter
FROM Purchasing.PurchaseOrders po
INNER JOIN Purchasing.PurchaseOrderLines pol
ON po.PurchaseOrderID=pol.PurchaseOrderID;
-- 2b
CREATE VIEW Purchasing.DetailedOrders
AS
SELECT
po.PurchaseOrderID
, po.SupplierID
, po.OrderDate
, po.ExpectedDeliveryDate
, pol.Description
, pol.ExpectedUnitPricePerOuter
FROM Purchasing.PurchaseOrders po
INNER JOIN Purchasing.PurchaseOrderLines pol
ON po.PurchaseOrderID=pol.PurchaseOrderID;
-- 2c
SELECT * FROM Purchasing.DetailedOrders;
Tworzenie widoku w bazach danych
Używając wieloczęściowego nazewnictwa, możemy odwoływać się do tabel w innej bazie danych. Dlatego możemy wykonywać JOIN w bazach danych i tworzyć widoki, które obejmują bazy danych. Jest to pomocne w przypadku niektórych aplikacji, które rozpowszechniają swoje dane w bazach danych w tej samej instancji SQL Server.
Listing 3 przedstawia podobny przypadek jak Listing 2, ale z jedną różnicą:do zapytania JOIN dodajemy trzecią tabelę z innej bazy danych. Zauważ, że musimy użyć LEFT OUTER JOIN, ponieważ między tabelami w obu bazach danych nie istnieje żaden rzeczywisty związek. Tutaj używamy go tylko do zilustrowania tworzenia WIDOKU, który obejmuje różne bazy danych.
W poleceniu CREATE VIEW wprowadziliśmy alias, ponieważ mamy kolumny z dwóch różnych tabel o tej samej nazwie. W takich przypadkach musimy rozróżnić te kolumny.
-- Listing 3: Creating a View Across Databases
-- 3a
SELECT
po.PurchaseOrderID
,po.SupplierID
,po.OrderDate
,po.ExpectedDeliveryDate
,pol.Description
,pol.ExpectedUnitPricePerOuter
,so.orderid
,so.custid
,so.orderdate
FROM Purchasing.PurchaseOrders po
INNER JOIN Purchasing.PurchaseOrderLines pol
ON po.PurchaseOrderID=pol.PurchaseOrderID
LEFT OUTER JOIN TSQLV4.Sales.Orders so
ON po.PurchaseOrderID=so.orderid;
-- 3b
CREATE VIEW Purchasing.DetailedOrdersDistributed
AS
SELECT
po.PurchaseOrderID
,po.SupplierID
,po.OrderDate
,po.ExpectedDeliveryDate
,pol.Description
,pol.ExpectedUnitPricePerOuter
,so.orderid
,so.custid
,so.orderdate AS OrdersOrderDate
FROM Purchasing.PurchaseOrders po
INNER JOIN Purchasing.PurchaseOrderLines pol
ON po.PurchaseOrderID=pol.PurchaseOrderID
LEFT OUTER JOIN TSQLV4.Sales.Orders so
ON po.PurchaseOrderID=so.orderid;
-- 3c
SELECT * FROM Purchasing.DetailedOrdersDistributed;
Spójrz na rysunek 1. Pokazuje on wynik wykonania Listingu 3(3c). Zauważ, że ostatnie trzy kolumny są puste, ponieważ TSQLV4.Sales.Orders tabela nie zawiera żadnych wierszy spełniających warunek JOIN.
Tworzenie widoku w różnych instancjach
Możemy rozszerzyć ostatnią wypowiedź, wprowadzając tabelę, która znajduje się całkowicie w innej instancji.
Aby to osiągnąć, musimy najpierw stworzyć Linked Server. Robimy to za pomocą kodu podobnego do pokazanego na Listingu 4.
-- Listing 4: Linked Server
USE [master]
GO
EXEC master.dbo.sp_addlinkedserver @server = N'IGIRI01\SQLEXPRESS', @srvproduct=N'SQL Server'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'IGIRI01\SQLEXPRESS',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL
GO
Zwróć uwagę, jak adresujemy zewnętrzną tabelę za pomocą czteroczęściowej nazwy:
-- Listing 5: Creating a View Across Instances
-- 5a
CREATE VIEW Purchasing.DetailedOrdersExternal
AS
SELECT
po.PurchaseOrderID
,po.SupplierID
,po.OrderDate
,po.ExpectedDeliveryDate
,pol.Description
,pol.ExpectedUnitPricePerOuter
,ipol.StockItemID
,ipol.LastEditedWhen
FROM Purchasing.PurchaseOrders po
INNER JOIN Purchasing.PurchaseOrderLines pol
ON po.PurchaseOrderID=pol.PurchaseOrderID
INNER JOIN [IGIRI01\SQLEXPRESS].[WWI].[Purchasing].[PurchaseOrderLines] ipol
ON po.PurchaseOrderID=ipol.PurchaseOrderID;
-- 5b
SELECT * FROM Purchasing.DetailedOrdersExternal;
Uwzględnianie funkcji w widokach
Ponieważ widoki są zasadniczo zapytaniami, możemy zastosować do nich prawie wszystko, co robimy ze zwykłymi zapytaniami. Możemy dołączyć funkcje, klauzule WHERE, wyrażenia CASE, aliasy itp.
Jednak klauzula ORDER BY nie jest dozwolona, z wyjątkiem użycia „hackowania TOP 100”. Listingi od 6 do 9 ilustrują użycie tych klauzul w widokach.
-- Listing 6: Creating a View with a Function
CREATE VIEW Purchasing.DetailedOrdersComplex
AS
SELECT
ipol.PurchaseOrderID
,ipol.Description
,ipol.ExpectedUnitPricePerOuter
,ipol.StockItemID
,CONVERT(VARCHAR, LastEditedWhen, 113) AS LastEditedLongDate
FROM [IGIRI01\SQLEXPRESS].[WWI].[Purchasing].[PurchaseOrderLines] ipol
-- Listing 7: Creating a View with a WHERE Clause
CREATE VIEW Purchasing.DetailedOrdersComplexFilt
AS
SELECT
ipol.PurchaseOrderID
,ipol.Description
,ipol.ExpectedUnitPricePerOuter
,ipol.StockItemID
,CONVERT(VARCHAR, LastEditedWhen, 113) AS LastEditedLongDate
FROM [IGIRI01\SQLEXPRESS].[WWI].[Purchasing].[PurchaseOrderLines] ipol
WHERE ipol.PurchaseOrderID<10;
-- Listing 8: Creating a View a TOP Clause
CREATE VIEW Purchasing.DetailedOrdersComplexTop
AS
SELECT TOP 10
ipol.PurchaseOrderID
,ipol.Description
,ipol.ExpectedUnitPricePerOuter
,ipol.StockItemID
,CONVERT(VARCHAR, LastEditedWhen, 113) AS LastEditedLongDate
FROM [IGIRI01\SQLEXPRESS].[WWI].[Purchasing].[PurchaseOrderLines] ipol
-- Listing 9: Creating a View with a CASE Expression
CREATE VIEW Purchasing.DetailedOrdersComplexTop
AS
SELECT TOP 10
CASE
ipol.PurchaseOrderID
WHEN 1 THEN 'First Order'
WHEN 2 THEN 'Second Order'
END PurchaseOrder
,ipol.Description
,ipol.ExpectedUnitPricePerOuter
,ipol.StockItemID
,CONVERT(VARCHAR, LastEditedWhen, 113) AS LastEditedLongDate
FROM [IGIRI01\SQLEXPRESS].[WWI].[Purchasing].[PurchaseOrderLines] ipol
Wyświetlenia zindeksowane
Odnieśliśmy się do widoków indeksowanych wcześniej w artykule. Widoki indeksowane mogą poprawić wydajność, z wyjątkiem przypadków, w których tabele bazowe wymagają intensywnego zapisu. SQL Server wymaga włączenia pewnych opcji SET przed utworzeniem widoków indeksowanych lub wykonaniem na nich pewnych operacji.
Klauzula WITH SCHEMABINDING powinna być używana podczas tworzenia widoku w celu umieszczenia na nim indeksu. Ta klauzula ściśle wiąże widok z podstawowymi obiektami. Dlatego takie obiekty nie mogą zostać upuszczone.
-- Listing 10: Creating an Indexed View
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS ON;
CREATE VIEW Purchasing.DetailedOrdersIndexed
WITH SCHEMABINDING
AS
SELECT
po.PurchaseOrderID
,po.SupplierID
,po.OrderDate
,po.ExpectedDeliveryDate
FROM Purchasing.PurchaseOrders po;
CREATE UNIQUE CLUSTERED INDEX IX_ID
ON Purchasing.DetailedOrdersIndexed (PurchaseOrderID);
Wniosek
W tym artykule przyjrzeliśmy się poglądom na pewnym poziomie szczegółowości. Pokrótce omówiliśmy typy widoków i podaliśmy kilka przykładów widoków zdefiniowanych przez użytkownika oraz tego, jak wykorzystaliśmy JOIN do realizacji widoków zależnych od wielu tabel. Omówiliśmy również złożone widoki, które zawierają funkcje, a także widoki indeksowane.
Referencje
- Widoki
- Wyświetlenia indeksowane
- Tworzenie indeksowanych widoków w SQL Server