视图 View

通过本文的学习,您将能够:

  • 创建视图

  • 用视图呈现派生和聚集数据

  • 使用视图向用户隐藏 联接

1. 什么是视图

E76BD~EHXBMORE4G1TPB2

  视图 经常被称作虚拟表 (Virtual Table) 在用户看来,它表现得如同一张普通表。但事实上,视图本身是不存在的。相反,它派生自实际表中的列。
  视图也被称作数据库上的动态窗口(Dynamic Window)

示例
视图可以存储 诸如价格总和(total_price ) 这类计算结果。由于个别价格改变,存储的价格总和总是最新的。

2. 创建视图

  CREATE VIEW 语句包含 CREATE VIEW 子句和 SELECT 语句。

  也可以在视图名称之后通过括号列出视图的各个列,为视图的列命名。如果不为列命名,视图将使用基础表中的列名。

  视图中的SELECT语句遵循编写 SELECT 语句的正常规则,但是以下语法被禁用:

  • FIRST
  • INTO TEMP

示例:

CREATE VIEW ordsummary AS
  SELECT order_num, customer_num, ship_date FROM orders;

CREATE VIEW they_owe (ordno, orddate, cnum) AS 
  SELECT order_num, order_date, customer_num
    FROM orders
  WHERE paid_date IS NULL;

  在第一个示例中,视图ordsummary 有三列。它们的列名称与orders 表中的列相同。

  在第二个示例中,视图 they_owe 也有三列。但是该视图的列名不同于 orders 表中的列名。它们被命名为ordno、orddatecnum ,而非 order_num、order_datecustomer_num 。另外,视图 they_owe 只展示了order表中 paid_date 为空的行。

3. 删除视图

DROP VIEW ordsummary;

  DROP VIEW 命令允许从数据库中删除视图。删除视图时,实际上并不会删除任何数据。基础表保持不变。

不能更改视图

  不能 ALTER 视图。要改变视图,必须先使用 DROP VIEW删除视图,然后使用 CREATE VIEW 重新创建视图。

4. 视图:访问列

CREATE VIEW ordsummary AS
  SELECT order_num, customer_num, ship_date
  FROM orders;

  视图可以限制对一个或多个表中某些列的访问。

  这可能很有用,原因有两个:

  • 某些列中的信息可能是敏感信息,应该禁止随意访问。例如,禁止所有用户访问雇员表中的工资列。

  • 某些列可能包含与一些用户不相关的数据。通过将这些列从视图中移除,数据库看上去更简洁清晰。

  在上述示例中,创建了只包含三列的视图:order_num customer_numship_date 。从该视图选择数据时,其他行将不会被列出。

5. 视图:访问行

以下示例展示了只列出 stock 表中的棒球设备的视图。

CREATE VIEW baseball AS 
  SELECT *
  FROM stock
  WHERE description MATCHES "*baseball*";

  视图可以限制对一个或多个表中某些行的访问。

  这可能很有用,原因有两个:

  • 某些行可以包含敏感数据或数据应被限定仅指定用户可访问。

  • 对特定用户而言,某些行可能并不重要。例如,收款部门可能只会对没有支付的订单感兴趣。

6. 视图:虚拟列

CREATE VIEW ship_cost (ordno, cnum, s_wt, 
    s_chg, chg_per_lb) AS
  SELECT ord_num, customer_num, ship_weight, ship_charge, 
    ship_charge / ship_weight
  FROM orders;

  可以通过使用包含表达式的 SELECT 语句创建视图。表达式的结果被称为虚拟列 (virtual column)

示例
  在上述示例中,视图包含计算的每公斤运费的列。每公斤运费的计算公式 :chg_per_lb = ship_charge / ship_weight 。用户查询视图时,视图中所有的虚拟列看上去都如同实际列一样。

  计算的结果:ship_charge / ship_weight展示在虚拟列 chg_per_lb 中。

7. 视图:聚集函数

CREATE VIEW manu_total (m_code, total_sold) AS
  SELECT manu_code, **SUM(total_price** )
    FROM items
    GROUP BY manu_code;

  也可以在视图的 SELECT 语句中使用聚集(aggregate)函数(即,SUM、MIN、MAX、AVG、COUNT)。

示例
  上述示例展示了按照不同的 manu_code 进行分组并计算各分组价格总和的视图。聚集函数被置于名为 total_sold 的虚拟列中。

8. 连接两张表的视图

CREATE VIEW stock_info AS 
  SELECT stock.*, manu_name 
  FROM stock, manufact 
  WHERE stock.manu_code =
    manufact.manu_code;

  可以通过视图向用户隐藏 联接。这使得复杂的联接对用户不可见。

示例

  在上述示例中,视图上的 SELECT 结果是对stockmanufact 表的数据的组合。视图创建一种有用的数据位于一张名为 stock_info 表中的错觉。对于用户而言,stock_info 看起来是一张表。

  实际上,stock_info 并不是一张真实存在的表,而是一个基于stock和manufact两张基础表上的视图。

9. 视图上的视图

CREATE VIEW manu_total
    (m_code,total_sold) AS
  SELECT manu_code, SUM(total_price)
  FROM items
  GROUP BY manu_code;

CREATE VIEW manu_new AS
  SELECT manu_name, total_sold
  FROM manufact, manu_total
  WHERE manufact.manu_code =
    manu_total.m_code;

  一个视图可以完全或部分基于另一个视图。

示例

  上述示例首先创建一个名为 manu_total 的视图,为每个 manu_code 组计算价格总和。视图 manu_new 把从 manu_total 视图选择的数据与 manufact 表中的 manu_name 列联接起来。

  视图展示了两部分数据:列 manu_name 和虚拟列 total_sold

10. 视图的限制条件

  视图有几个限制条件:

  • 不能在视图上创建索引。但是在查询时,可以利用基础表列上已存在的索引。

  • 视图取决于其基础表(和视图)。如果删除表,派生自该表的所有视图都会被自动删除。如果删除视图,派生自该视图的所有视图都会被自动删除。

  • 某些视图限制插入、更新和删除操作。这些限制将在后面进行描述。

  • 必须在视图的所有列上拥有SELECT 特权才能在表上创建视图。

10.1 视图:INSERT、UPDATE 和 DELETE

  • 不能对视图进行 INSERT、UPDATE 或 DELETE操作,如果它有:
    一个联接
    一个聚合

  • 不能UPDATE包含虚拟列的视图

  • 不能INSERT包含虚拟列的视图

  • 可以DELETE 包含虚拟列的视图

11. WITH CHECK OPTION 子句

  截至目前我们创建的视图允许您把行插入数据库中,*即使那些行在视图范围之外。*带有 CHECK 选项的视图给予数据库管理员额外的安全级别。数据库管理员可以要求使用视图在表中进行更新、删除或插入操作。如以下示例所示,该视图可以对表内的特定行强制限定条件。

对比示例:

CREATE VIEW no_check AS
  SELECT * FROM stock
  WHERE manu_code = "HRO";

CREATE VIEW yes_check AS
  SELECT * FROM stock
  WHERE manu_code = "HRO"
  WITH CHECK OPTION;

  例如,视图no_check 允许 INSERT 行,行的manu_code 值不是HRO ,INSERT 的每一行将立即变得无法通过视图访问。

  可以在 CREATE VIEW 语句末尾使用 WITH CHECK OPTION 子句修正该情况。视图 yes_check 允许只插入满足视图选择条件的数据。

  

以下哪一个会成功,为什么?

INSERT INTO no_check
  VALUES (1, "ANZ", "soccer ball", 30,
    "each", "each");

INSERT INTO yes_check
  VALUES (1, "ANZ", "soccer ball", 30,
    "each", "each");

  以上示例展示了在不使用 WITH CHECK OPTION 子句的情况下,会发生什么:

  • 用户通过视图 no_check 插入一行。

  • 稍后,用户运行这条语句:
    SELECT * FROM no_check

  • 新增加的行不出现在输出里。

  • 如果用户使用 yes_check 而非 no_check ,那么INSERT会被拒绝,并产生错误信息(Data value out of range )。

13. 视图和访问特权

REVOKE ALL ON stock FROM PUBLIC;

REVOKE ALL ON stock_info FROM PUBLIC;

GRANT SELECT ON stock_info TO dennis, karen, mari;

  可以把视图当作表,并在视图上 GRANT 和 REVOKE 表级特权。但是,如果这种特权违反在视图的限制条件 下讨论的规则,那么就不能授予 INSERT、UPDATE 和 DELETE 特权。同样的,ALTER 特权也不可用于视图。

  可以在表上撤销特权,然后在可以访问该表的视图上授予特权,强制用户使用视图去访问表。

示例
  在上述示例中,执行语句之后,除非通过使用stock_info 视图,否则没有用户可以访问stock 表。

14. 视图的系统目录

  • sysviews
    存储 CREATE VIEW 语句。

  • sysdepend
    每个视图对应的基础表和/或视图。

  • systables
    存储在在systables表中且tabtype=“V”