18 使用视图
1.视图
视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
第12课的列子,用SELECT语句从三个表中检索数据,列出订购物品'RGAN01'的所有顾客。输入:
SELECT cust_name, cust_contact
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id= 'RGAN01';
输出:
要检索其他产品的相同数据,必须修改最后的WHERE子句。
假设可以把整个查询包装成一个名为ProductCustomers的虚拟表,可以如下检索出相同的数据,输入:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id= 'RGAN01';
ProductCustomers是一个视图,不包含任何列或查询,包含的是一个查询。
(1)为什么使用视图
视图的常见应用:
-
重用SQL语句;
-
简化复杂的SQL操作,在编写查询后,可以方便地重用它,而不必知道其基本查询细节;
-
使用表的一部分而不是整个表;
-
保护数据,可以之手与用户访问表的特定部分的权限;
-
更改数据格式和表示,可以返回与底层表的表示和格式不同的数据。
可以对视图执行与表相同的使用方式,如SELECT操作,过滤和排序数据,将视图联结到其他视图或表,添加和更新数据。
(2)视图的规则和限制
-
与表一样,视图必须唯一命名(不能与其他视图或表重名);
-
对于可以创建的视图数目没有限制;
-
创建视图,必须有足够的访问权限;
-
视图可以嵌套,但所允许的嵌套层数可能不同;
-
许多DBMS禁止在视图查询中年使用ORDER BY子句;
-
有些DBMS要求对返回的所有列进行命名,如果列是计算字段,则需要使用别名;
-
视图不能索引,也不能有关联的触发器或默认值;
-
有些DBMS把视图作为只读的查询,即可以从视图检索数据,但不能将数据写回底层表;
-
有些DBMS允许创建这样的视图,它不能进行导致行不再属于视图的插入或更新。
2.创建视图
用CREATE VIEW语句来创建视图,只能用于创建不存在的视图。
(1)利用视图简化复杂的联结
一个最常见的视图应用是隐藏复杂的SQL。
输入:
CREATE VIEW ProductCustomers AS
SELECT cust_name, cust_contact, prod_id
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num;
此SQL语句创建一个名为ProductCustomers的视图,它联结三个表:Customers、Orders和OrderItems,返回已订购了任意产品的所有顾客的列表。
检索订购了产品RGAN01的顾客,输入:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
输出:
如果执行SELECT * FROM ProductCustomers,输出订购了任意产品的顾客。
该SQL语句通过WHERE子句从视图中检索特定数据。
(2)用视图重新格式化检索出数据
第7课中,使用SELECT语句,在单个组合计算列中返回供应商和位置。
输入:
SELECT Concat(vend_name, ' (', RTRIM(vend_country), ')')
AS vend_title
FROM Vendors
ORDER BY vend_name;
输出:
下面使用了||语法,输入:
SELECT RTRIM(vend_name) || ' (', RTRIM(vend_country) || ')'
AS vend_title
FROM Vendors
ORDER BY vend_name;
输出:好像不适用于MySQL
将该查询转换为视图,输入:
CREATE VIEW VendorLocations AS
SELECT Concat(vend_name, ' (', RTRIM(vend_country), ')')
AS vend_title
FROM Vendors;
要检索数据,创建所有的邮件标签,输入:
SELECT *
FROM VendorLocations;
输出:
(3)用视图过滤不想要的数据
视图对于应用普通的WHERE子句也很有用。例如,可以定义CustomersEMailList视图,过滤没有电子邮件的顾客。输入:
CREATE VIEW CustomersEMailList AS
SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
删除:DROP VIEW CustomersEMailList;
输入:
SELECT *
FROM CustomersEMailList
WHERE cust_email IS NOT NULL;
输出:
怎样过滤掉NULL的数据?
(4)使用视图与计算字段
输入:
SELECT prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
输出:
将其准换为一个视图,输入:
CREATE VIEW OrderItemsExpanded AS
SELECT order_num,
prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM OrderItems;
检索订单20008的详细内容,输入:
SELECT *
FROM OrderItemsExpanded
WHERE order_num = 20008;
输出: