视图是一种虚拟的数据表,它们的行为和数据表一样,但并不真正包含数据。它们是用底层(真
正的)数据表或其他视图定义出来的“假”数据表,用来提供查看数据表数据的另一种方法,这通常可以简化应用程序。
本节重点介绍视图的一些应用。这里没有讨论 DEFINER子句,这个子句是存储程序和视图都使用
的,它可以用来从信息安防的角度对视图数据的访问情况进行控制。如果要选取某给定数据表的数据列的一个子集,把它定义为一个简单的视图是最方便的做法。比
如说,假设你经常需要从 president数据表选取 last_name、first_name、city和 state等几个
数据列,但不想每次都必须写出所有这些数据列,如下所示:
SELECT last_name, first_name, city, state FROM president;
你也不想使用 SELECT
*,这虽然简单,但用*检索出来的数据列不都是你想要的。解决这个矛盾
的办法是定义一个视图,让它只包括你想要的数据列:
CREATE VIEW vpres AS
SELECT last_name, first_name, city, state FROM president;
这个视图就像一个“窗口”,从中只能看到你想看的数据列。这意味着你可以在这个视图上使用SELECT *,而你看到的将是你在视图定义里给出的那些数据列:
mysql> SELECT
* FROM vpres;
+------------+---------------+---------------------+-------+
| last_name | first_name | city | state |
+------------+---------------+---------------------+-------+
| Washington
| George
| Wakefield
| VA
|
| Adams
| John
| Braintree
| MA
|
| Jefferson
| Thomas
| Albemarle County
| VA
|
| Madison
| James
| Port Conway
| VA
|
| Monroe
| James
| Westmoreland Count
y | VA
|
...
如果你在查询某个视图时还使用了一个 WHERE子句,MySQL
将在执行该查询时把它添加到那个视图的定义上以进一步限制其检索结果:
mysql> SELECT
* FROM vpres WHERE last_name = 'Adams';
+-----------+-------------+-----------+-------+
| last_name | first_name | city | state |
+-----------+-------------+-----------+-------+
| Adams | John | Braintree | MA |
| Adams | John Quincy | Braintree | MA |
+-----------+-------------+-----------+-------+
在查询视图时还可以使用 ORDER
BY、LIMIT等子句,其效果与查询一个真正的数据表时的情况
一样。在使用视图时,你只能引用在该视图的定义里列出的数据列。也就是说,如果底层数据表里的某个数据列没在视图的定义里,你在使用视图的时候就不能引用它:
mysql> SELECT
* FROM vpres WHERE suffix <> '';
ERROR 1054 (42S22): Unknown column 'suffix' in 'where clause'
在默认的情况下,视图里的数据列的名字与 SELECT语句里列出的输出数据列相同。如果你想明
确地改用另外的数据列名字,需要在定义视图时在视图名字的后面用括号列出那些新名字:
mysql> CREATE
VIEW vpres2 (ln, fn) AS
-> SELECT
last_name, first_name FROM president;
此后,当你使用这个视图时,必须使用在括号里给出的数据列名字,而非 SELECT语句里的名字:
mysql> SELECT
last_name, first_name FROM vpres2;
ERROR 1054 (42S22) at line 1: Unknown column 'last_name' in 'field
list' mysql> SELECT
ln, fn FROM vpres2;
+------------+---------------+
| ln | fn |
+------------+---------------+
| Washington
| George
|
| Adams
| John
|
| Jefferson
| Thomas
|
| Madison
| James
|
| Monroe | James |
...
视图可以用来自动完成必要数学运算。
mysql> CREATE
VIEW pres_age AS
-> SELECT
last_name, first_name, birth, death,
-> TIMESTAMPDIFF(YEAR,
birth, death) AS age
-> FROM
president;
这个视图包含一个 age数据列,它被定义成一个运算,从这个视图选取该数据列将检索出这个运算的结果:
mysql> SELECT
* FROM pres_age;
+------------+---------------+------------+------------+------+
| last_name | first_name | birth | death | age |
+------------+---------------+------------+------------+------+
| Washington
| George
| 1732-02-22 | 1799-12-14 |
67 |
| Adams
| John
| 1735-10-30 | 1826-07-04 |
90 |
| Jefferson
| Thomas
| 1743-04-13 | 1826-07-04 |
83 |
| Madison
| James
| 1751-03-16 | 1836-06-28 |
85 |
| Monroe
| James
| 1758-04-28 | 1831-07-04 |
73 |
...
通过把年龄计算工作放到视图定义里完成,我们就用不着再在查询年龄值时写出那个公式了。有关的细节都隐藏在了视图里。
同一个视图可以涉及多个数据表,这使得联结查询的编写和运行变得更容易。下面定义的视图对score、student 和grade_event 数据表进行了联结查询:
mysql> CREATE
VIEW vstudent AS
-> SELECT
student.student_id, name, date, score, category
-> FROM
grade_event INNER JOIN score INNER JOIN student
-> ON
grade_event.event_id = score.event_id
-> AND
score.student_id = student.student_id;
当你从这个视图选取数据时,MySQL 将执行相应的联结查询并从多个数据表返回信息:
mysql> SELECT
* FROM vstudent;
+------------+-----------+------------+-------+----------+
| student_id | name | date | score | category |
+------------+-----------+------------+-------+----------+
|
1 | Megan
| 2008-09-03 |
20 | Q
|
|
3 | Kyle
| 2008-09-03 |
20 | Q
|
|
4 | Katie
| 2008-09-03 |
18 | Q
|
|
5 | Abby
| 2008-09-03 |
13 | Q
|
|
6 | Nathan
| 2008-09-03 |
18 | Q
|
|
7 | Liesl
| 2008-09-03 |
14 | Q
|
|
8 | Ian
| 2008-09-03 |
14 | Q
|
...
这个视图可以让我们轻而易举地根据名字检索出某个学生的考试成绩:
mysql> SELECT
* FROM vstudent WHERE name = 'emily';
+------------+-------+------------+-------+----------+
| student_id | name | date | score | category |