Introduzione
Una vista in SQL Server è una struttura virtuale simile a una tabella basata sul set di risultati di un'istruzione SQL. In superficie, una vista è simile a una tabella con la struttura della firma di righe e colonne. Tuttavia, queste righe e colonne provengono da tabelle a cui si fa riferimento nella query, che definisce la vista.
Usiamo le viste per concentrarci sulle colonne concrete per gli scopi per cui sono state create. Le visualizzazioni possono servire anche per motivi di sicurezza. Filtrano le colonne nelle tabelle sottostanti che non si vogliono rendere visibili a determinati utenti. Visualizza le colonne dei filtri come una clausola WHERE filtra le righe.
Un altro motivo per Views è la semplicità. Aggregano colonne di diverse tabelle e creano un aspetto generale simile a un'unica tabella.
Tipi di visualizzazioni
Le visualizzazioni di base definite dall'utente sono facili da creare. Il processo è simile alla scrittura di query che fanno riferimento a una o più tabelle.
- Le viste indicizzate sono quelle che sono state materializzate o archiviate come una tabella. Le viste indicizzate possono migliorare le prestazioni delle query che aggregano molte righe. Tuttavia, non sono adatti se le tabelle sottostanti vengono aggiornate frequentemente.
- Le viste partizionate uniscono dati partizionati orizzontalmente da tabelle in locale (all'interno della stessa istanza) o in più, utilizzando server collegati.
- Le visualizzazioni di sistema sono le strutture comuni utilizzate da SQL Server per esporre i metadati del catalogo. Le visualizzazioni di sistema sono la maggior parte di quelle strutture che si interrogano per la risoluzione dei problemi delle prestazioni o per l'analisi di un'istanza di SQL Server.
Creazione di una vista da una tabella
Dai un'occhiata all'esempio nel Listato 1. La prima istruzione restituisce TUTTI i record nella tabella Purchasing.PurchaseOrders (1a), mentre la seconda query restituisce solo poche colonne (1b).
Usando la seconda query, possiamo creare una vista che restituisce lo stesso set di risultati di (1b). Quando lo facciamo, possiamo interrogare una vista per ottenere l'output desiderato. Pertanto, semplifichiamo la query per un utente finale.
-- 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 ;
Creazione di una vista da due tabelle
Utilizzando JOIN, possiamo recuperare i dati da due o più tabelle che hanno una relazione. Utilizzando Views, possiamo semplificare l'accesso a tali dati.
Il Listato 2 (2a) mostra un JOIN tra Purchasing.PurchaseOrders e Purchasing.PurchaseOrderLines. Possiamo creare una vista da questo JOIN e ci consentirà di recuperare gli stessi dati utilizzando una query, come mostrato in (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;
Creazione di una vista sui database
Usando la denominazione in più parti, possiamo fare riferimento a tabelle in un database diverso. Pertanto, possiamo eseguire JOIN tra i database e creare viste che si estendono su database. È utile per alcune applicazioni che diffondono i propri dati tra i database nella stessa istanza di SQL Server.
Il Listato 3 mostra un caso simile al Listato 2, ma con una differenza:aggiungiamo una terza tabella alla query JOIN da un database diverso. Si noti che dobbiamo usare un LEFT OUTER JOIN poiché non esiste alcuna relazione reale tra le tabelle in entrambi i database. Qui lo usiamo solo per illustrare la creazione di una VIEW che si estende su database diversi.
Abbiamo introdotto un alias nell'istruzione CREATE VIEW, poiché abbiamo colonne di due tabelle diverse con lo stesso nome. Dobbiamo distinguere queste colonne in questi casi.
-- 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;
Dai un'occhiata alla Figura 1. Mostra il risultato dell'esecuzione del Listato 3(3c). Nota che le ultime tre colonne sono vuote, come TSQLV4.Sales.Orders la tabella non ha righe corrispondenti alla condizione JOIN.
Creazione di una vista tra le istanze
Possiamo estendere l'ultima affermazione introducendo una tabella che risiede interamente in un'altra istanza.
Per raggiungere questo obiettivo, dobbiamo prima creare un server collegato. Lo facciamo con il codice simile a quello mostrato nel Listato 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
Nota come indirizziamo la tabella esterna usando un nome in quattro parti:
-- 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;
Inclusione di funzioni nelle viste
Poiché le visualizzazioni sono essenzialmente query, possiamo applicarle quasi tutto ciò che facciamo con le query regolari. Possiamo includere funzioni, clausole WHERE, espressioni CASE, alias, ecc.
Tuttavia, la clausola ORDER BY non è consentita, a meno che tu non utilizzi il "TOP 100 hack". Gli elenchi da 6 a 9 illustrano l'utilizzo di tali clausole in Visualizzazioni.
-- 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
Viste indicizzate
Abbiamo fatto riferimento alle viste indicizzate in precedenza nell'articolo. Le viste indicizzate possono migliorare le prestazioni, ad eccezione dei casi in cui le tabelle sottostanti richiedono un uso intensivo della scrittura. SQL Server richiede determinate opzioni SET abilitate prima di creare viste indicizzate o eseguire determinate operazioni su di esse.
La clausola WITH SCHEMABINDING deve essere utilizzata durante la creazione di una vista per inserire un indice su di essa. Questa clausola associa rigorosamente la vista agli oggetti sottostanti. Pertanto, tali oggetti non possono essere lasciati cadere.
-- 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);
Conclusione
In questo articolo, abbiamo esaminato le visualizzazioni a un certo livello di dettaglio. Abbiamo trattato brevemente i tipi di viste e fornito diversi esempi di viste definite dall'utente e come abbiamo utilizzato le JOIN per realizzare viste che dipendono da molte tabelle. Abbiamo anche trattato viste complesse che includono funzioni e viste indicizzate.
Riferimenti
- Viste
- Viste indicizzate
- Crea viste indicizzate in SQL Server