Introducción
Una vista en SQL Server es una estructura similar a una tabla virtual basada en el conjunto de resultados de una instrucción SQL. En la superficie, una vista es similar a una tabla con la estructura característica de filas y columnas. Sin embargo, estas filas y columnas provienen de las tablas a las que se hace referencia en la consulta, que define la Vista.
Usamos Vistas para centrarnos en las columnas concretas para los fines para los que fueron creadas. Las vistas también pueden servir por motivos de seguridad. Filtran columnas en las tablas subyacentes que uno no quiere que sean visibles para ciertos usuarios. Las vistas filtran las columnas como una cláusula WHERE filtra las filas.
Otra razón para Views es la simplicidad. Agregan columnas de varias tablas diferentes y crean una apariencia general que parece una sola tabla.
Tipos de Vistas
Las vistas básicas definidas por el usuario son fáciles de crear. El proceso es similar a escribir consultas que hacen referencia a una o más tablas.
- Las vistas indexadas son aquellas que se han materializado o almacenado como una tabla. Las vistas indexadas pueden mejorar el rendimiento de las consultas que agregan muchas filas. Sin embargo, no son adecuados si las tablas subyacentes se actualizan con frecuencia.
- Las vistas particionadas unen datos particionados horizontalmente de tablas localmente (dentro de la misma instancia) o en muchas, utilizando servidores vinculados.
- Las vistas del sistema son las estructuras comunes que utiliza SQL Server para exponer los metadatos del catálogo. Las vistas del sistema son la mayoría de esas estructuras que uno consulta para solucionar problemas de rendimiento o investigar una instancia de SQL Server.
Crear una vista desde una tabla
Eche un vistazo al ejemplo en el Listado 1. La primera declaración devuelve TODOS los registros en la tabla Compras.Pedidos de compra (1a), mientras que la segunda consulta devuelve solo unas pocas columnas (1b).
Usando la segunda consulta, podemos crear una Vista que devuelva el mismo conjunto de resultados que (1b). Cuando hacemos esto, podemos consultar una Vista para obtener el resultado deseado. Por lo tanto, simplificamos la consulta para un usuario final.
-- 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 ;
Crear una vista a partir de dos tablas
Al usar JOIN, podemos recuperar datos de dos o más tablas que tienen una relación. Con Views, podemos simplificar el acceso a dichos datos.
El Listado 2 (2a) muestra un JOIN entre Purchasing.PurchaseOrders y Purchasing.PurchaseOrderLines. Podemos crear una vista desde este JOIN, y nos permitirá recuperar los mismos datos usando una consulta, como se muestra en (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;
Crear una vista a través de bases de datos
Usando nombres de varias partes, podemos hacer referencia a tablas en una base de datos diferente. Por lo tanto, podemos hacer JOIN en las bases de datos y crear vistas que abarquen las bases de datos. Es útil para ciertas aplicaciones que distribuyen sus datos entre bases de datos en la misma instancia de SQL Server.
El Listado 3 muestra un caso similar al del Listado 2, pero con una diferencia:agregamos una tercera tabla a la consulta JOIN desde una base de datos diferente. Tenga en cuenta que tenemos que usar LEFT OUTER JOIN ya que no existe una relación real entre las tablas en ambas bases de datos. Aquí, lo usamos solo para ilustrar la creación de una VISTA que abarca diferentes bases de datos.
Hemos introducido un alias en la declaración CREATE VIEW, ya que tenemos columnas de dos tablas diferentes con el mismo nombre. Debemos distinguir esas columnas en tales casos.
-- 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;
Eche un vistazo a la Figura 1. Muestra el resultado de ejecutar el Listado 3(3c). Tenga en cuenta que las últimas tres columnas están vacías, ya que TSQLV4.Sales.Orders la tabla no tiene filas que coincidan con la condición JOIN.
Crear una vista a través de instancias
Podemos extender la última declaración introduciendo una tabla que vive en otra instancia por completo.
Para lograr esto, primero debemos crear un Servidor Enlazado. Lo hacemos con un código similar al que se muestra en el Listado 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
Observe cómo nos dirigimos a la tabla externa usando un nombre de cuatro partes:
-- 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;
Inclusión de funciones en vistas
Dado que las vistas son esencialmente consultas, podemos aplicarles casi cualquier cosa que hagamos con las consultas regulares. Podemos incluir funciones, cláusulas WHERE, expresiones CASE, alias, etc.
Sin embargo, la cláusula ORDER BY no está permitida, excepto que utilice el "TOP 100 hack". Los listados 6 a 9 ilustran el uso de esas cláusulas en Vistas.
-- 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
Vistas indexadas
Nos referimos a Vistas indexadas anteriormente en el artículo. Las vistas indexadas pueden mejorar el rendimiento, excepto en los casos en que las tablas subyacentes requieren mucha escritura. SQL Server requiere ciertas opciones SET habilitadas antes de crear vistas indexadas o realizar ciertas operaciones en ellas.
La cláusula WITH SCHEMABINDING debe usarse al crear una vista para ponerle un índice. Esta cláusula asocia estrictamente la Vista con los objetos subyacentes. Por lo tanto, dichos objetos no se pueden dejar caer.
-- 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);
Conclusión
En este artículo, hemos examinado las vistas con cierto nivel de detalle. Cubrimos brevemente los tipos de vistas y dimos varios ejemplos de vistas definidas por el usuario y cómo usamos JOIN para realizar vistas que dependen de muchas tablas. También cubrimos vistas complejas que incluyen funciones y vistas indexadas.
Referencias
- Vistas
- Vistas indexadas
- Crear vistas indexadas en SQL Server