Mysql 复习笔记- 基础篇4 [子查询&&联结表&&左连接&&右链接&&内连接]

子查询&&联结表&&左连接&&右链接&&内连接

子查询

下列是关于子查询使用

利用子查询进行过滤

列出够物品RGAN01的所有客户。

检索包含物品RGAN01的所有订单编号。

检索具有前一步骤列出的订单编号所有客户ID。

检索前一步骤返回的所有客户ID的客户信息。

 SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01';

解释: 列出所有RGAN01订单物品

 SELECT cust_id FROM Orders WHERE order_num IN (20007, 20008);

把上面两个查询组合成子查询

SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01');
  • 子查询是从内向外处理
  • 先执行 SELECT order_num FROM OrderItems WHERE prod_id = ‘RGAN01’
  • 把返回的订单号,20007,20008两个值以IN操作符用逗号格式传递给外部查询,
  • 再用SELECT cust_id FROM orders WHERE order_num IN (20007,20008)

检索客户的ID

SELECT cust_name, cust_contact FROM Customers WHERE cust_id IN (SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'RGAN01'));
  • 解释:

    • SELECT order_num FROM OrderItems WHERE prod_id = ‘RGAN01’ 查询返回订 单列表

    • 把上面的查询结果,给予 SELECT cust_id FROM Orders, 返回客户ID

    • 拿到返回的客户ID给予外层WHERE子句查询。

      注意: 子查询只能返回单个列。

作为计算字段使用子查询

例子:计算Customers中每个客户订单总数。

  • 从Customers 表中检索客户列表
  • 对检索出来的每个客户,统计其在Orders表中的订单数目。

单个客户查询

 SELECT COUNT(*) AS orders FROM Orders WHERE cust_id ='1000000001';

对每个客户执行COUNT(*)

SELECT cust_name,cust_state, (SELECT COUNT(*) FROM Orders WHERE Orders.cust_id = Customers.cust_id) AS orders FROM Customers ORDER BY cust_name;

解释: 对Customers表返回三列, cust_name , cust_state , orders .orders 是计算字

段,由 (SELECT COUNT(*) FROM Orders WHERE Orders.cust_id = Customers.cust_id) 建 立。每检索一个客户,执行一次计算,

Orders.cust_id = Customers.cust_id , 其中的句号,表示指定限定表名跟列,如果不具体指定

表名,列名,将返回Orders 表中的订单总数。如下:

SELECT cust_name, cust_state,(SELECT COUNT(*) FROM Orders WHERE cust_id = cust_id) AS orders FROM Customers ORDER BY cust_name;

联结表

关系表

例子: 一个包含目录的数据库,其中每种类型物品占用一行,每种物品要存储的信息包括产品描述 和价格,以及生产该产品的供应商信息。

有一个供应商生产多种物品,何处存储供应商的信息(地址,电话等),如何分开存储。

  1. 同一个供应商存储的信息都是相同的,每种产品重复信息,浪费空间
  2. 如果供应商信息改变,执行改一次。
  3. 重复数据,难保证每次储存信息一致,不一致信息难管理,利用。

关系数据库设计:

  • 避免相同数据出现多次
  • 信息被分解成一种数据,一个表
  • 各表通过某些常用值相互关联

上面的例子,设计两个表,一个存储供应商信息,一个存储产品信息。

  • Vendors 表包含所有供应商信息,供应商的primary key 唯一的标识值vend_id
  • Products表只存储产品信息,与供应商的primary key vend_id 表关联,利用供应商的 ID从Vendors表中找出相应的供应商详细信息。

这样的设计刚好符合上面3点。

关系数据库优点可伸缩性(scale),能够适应不断增加的工作量。

使用联结的好处

分解多个表方便存储,方便处理,可伸缩性强。

使用链接可以用一条SELECT中关联多个表返回一组输出。

注意:在设计关系数据库,避免在另一个关系表中插入非法的ID,可以设置关系表中值,只出现合法的值

创建联结

链接多个表

mysql> SELECT vend_name, prod_name, prod_price
    -> FROM Vendors, Products
    -> WHERE Vendors.vend_id = Products.vend_id;
+-----------------+---------------------+------------+
| vend_name       | prod_name           | prod_price |
+-----------------+---------------------+------------+
| Bears R Us      | 8 inch teddy bear   |       5.99 |
| Bears R Us      | 12 inch teddy bear  |       8.99 |
| Bears R Us      | 18 inch teddy bear  |      11.99 |
| Doll House Inc. | Fish bean bag toy   |       3.49 |
| Doll House Inc. | Bird bean bag toy   |       3.49 |
| Doll House Inc. | Rabbit bean bag toy |       3.49 |
| Doll House Inc. | Raggedy Ann         |       4.99 |
| Fun and Games   | King doll           |       9.49 |
| Fun and Games   | Queen doll          |       9.49 |
+-----------------+---------------------+------------+
9 rows in set (0.00 sec)

解释:

  • SELECT vend_name, prod_name, prod_price 指定检索的列,prod_name, prod_price 在同一个表。vend_name 在另外一个表
  • From 指定联结两个表Vendors, Products
  • WHERE子句限定 Vendors.vend_id = Products.vend_id 完全限定名。

WHERE子句的重要

  • 笛卡儿积(cartesian product) 由没有联结的条件表关系返回的结果,

保证所有联结都有WHERE子句,否则返回比的数据会比想要的数据多很多。

mysql> SELECT vend_name, prod_name, prod_price
    -> FROM Vendors, Products;
+-----------------+---------------------+------------+
| vend_name       | prod_name           | prod_price |
+-----------------+---------------------+------------+
| Bear Emporium   | Fish bean bag toy   |       3.49 |
| Bears R Us      | Fish bean bag toy   |       3.49 |
| Doll House Inc. | Fish bean bag toy   |       3.49 |
| Fun and Games   | Fish bean bag toy   |       3.49 |
| Furball Inc.    | Fish bean bag toy   |       3.49 |
| Jouets et ours  | Fish bean bag toy   |       3.49 |
| Bear Emporium   | Bird bean bag toy   |       3.49 |
| Bears R Us      | Bird bean bag toy   |       3.49 |
| Doll House Inc. | Bird bean bag toy   |       3.49 |
| Fun and Games   | Bird bean bag toy   |       3.49 |
| Furball Inc.    | Bird bean bag toy   |       3.49 |
| Jouets et ours  | Bird bean bag toy   |       3.49 |
| Bear Emporium   | Rabbit bean bag toy |       3.49 |
| Bears R Us      | Rabbit bean bag toy |       3.49 |
| Doll House Inc. | Rabbit bean bag toy |       3.49 |
| Fun and Games   | Rabbit bean bag toy |       3.49 |
| Furball Inc.    | Rabbit bean bag toy |       3.49 |
| Jouets et ours  | Rabbit bean bag toy |       3.49 |
| Bear Emporium   | 8 inch teddy bear   |       5.99 |
| Bears R Us      | 8 inch teddy bear   |       5.99 |
| Doll House Inc. | 8 inch teddy bear   |       5.99 |
| Fun and Games   | 8 inch teddy bear   |       5.99 |
| Furball Inc.    | 8 inch teddy bear   |       5.99 |
| Jouets et ours  | 8 inch teddy bear   |       5.99 |
| Bear Emporium   | 12 inch teddy bear  |       8.99 |
| Bears R Us      | 12 inch teddy bear  |       8.99 |
| Doll House Inc. | 12 inch teddy bear  |       8.99 |
| Fun and Games   | 12 inch teddy bear  |       8.99 |
| Furball Inc.    | 12 inch teddy bear  |       8.99 |
| Jouets et ours  | 12 inch teddy bear  |       8.99 |
| Bear Emporium   | 18 inch teddy bear  |      11.99 |
| Bears R Us      | 18 inch teddy bear  |      11.99 |
| Doll House Inc. | 18 inch teddy bear  |      11.99 |
| Fun and Games   | 18 inch teddy bear  |      11.99 |
| Furball Inc.    | 18 inch teddy bear  |      11.99 |
| Jouets et ours  | 18 inch teddy bear  |      11.99 |
| Bear Emporium   | Raggedy Ann         |       4.99 |
| Bears R Us      | Raggedy Ann         |       4.99 |
| Doll House Inc. | Raggedy Ann         |       4.99 |
| Fun and Games   | Raggedy Ann         |       4.99 |
| Furball Inc.    | Raggedy Ann         |       4.99 |
| Jouets et ours  | Raggedy Ann         |       4.99 |
| Bear Emporium   | King doll           |       9.49 |
| Bears R Us      | King doll           |       9.49 |
| Doll House Inc. | King doll           |       9.49 |
| Fun and Games   | King doll           |       9.49 |
| Furball Inc.    | King doll           |       9.49 |
| Jouets et ours  | King doll           |       9.49 |
| Bear Emporium   | Queen doll          |       9.49 |
| Bears R Us      | Queen doll          |       9.49 |
| Doll House Inc. | Queen doll          |       9.49 |
| Fun and Games   | Queen doll          |       9.49 |
| Furball Inc.    | Queen doll          |       9.49 |
| Jouets et ours  | Queen doll          |       9.49 |
+-----------------+---------------------+------------+
54 rows in set (0.00 sec

上面的例子包含很多,不正确的数据。

内部联结

基于两边直接的相对测试,称为等值联结(euqijoin)

mysql> SELECT vend_name, prod_name, prod_price
    -> FROM Vendors INNER JOIN Products
    -> ON Vendors.vend_id = Products.vend_id;
+-----------------+---------------------+------------+
| vend_name       | prod_name           | prod_price |
+-----------------+---------------------+------------+
| Bears R Us      | 8 inch teddy bear   |       5.99 |
| Bears R Us      | 12 inch teddy bear  |       8.99 |
| Bears R Us      | 18 inch teddy bear  |      11.99 |
| Doll House Inc. | Fish bean bag toy   |       3.49 |
| Doll House Inc. | Bird bean bag toy   |       3.49 |
| Doll House Inc. | Rabbit bean bag toy |       3.49 |
| Doll House Inc. | Raggedy Ann         |       4.99 |
| Fun and Games   | King doll           |       9.49 |
| Fun and Games   | Queen doll          |       9.49 |
+-----------------+---------------------+------------+
9 rows in set (0.01 sec)

联结多个表

先列出所有列,再定义表之间的关系。

mysql> SELECT prod_name, vend_name, prod_price, quantity
    -> FROM OrderItems, Products, Vendors
    -> WHERE Products.vend_id = Vendors.vend_id
    -> AND OrderItems.prod_id = Products.prod_id
    -> AND order_num = 20007;
+---------------------+-----------------+------------+----------+
| prod_name           | vend_name       | prod_price | quantity |
+---------------------+-----------------+------------+----------+
| 18 inch teddy bear  | Bears R Us      |      11.99 |       50 |
| Fish bean bag toy   | Doll House Inc. |       3.49 |      100 |
| Bird bean bag toy   | Doll House Inc. |       3.49 |      100 |
| Rabbit bean bag toy | Doll House Inc. |       3.49 |      100 |
| Raggedy Ann         | Doll House Inc. |       4.99 |       50 |
+---------------------+-----------------+------------+----------+
5 rows in set (0.00 sec)

返回订购产品RGAN01的客户列表

mysql> SELECT cust_name, cust_contact
    -> FROM Customers
    -> WHERE cust_id IN (SELECT cust_id
    -> FROM Orders
    -> WHERE order_num IN (SELECT order_num
    -> FROM OrderItems
    -> WHERE prod_id = 'RGAN01'));
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set (0.00 sec)

下面使用联结查询

mysql> 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';
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set (0.00 sec)

解释:返回的数据需要使用3个表,三个WHERE子句,最后过滤出RGAN01产品的数据

创建高级链接-内链接

使用表别名

  • 目的在于缩短SQL语句
  • 运行单条SELECT 语句中多次使用相同的表。
mysql> SELECT cust_name, cust_contact FROM Customers AS C, Orders AS O, OrderItems AS OI WHERE C.cust_id = O.cust_id AND OI.order_num = O.order_num AND prod_id = 'RGAN01';
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set (0.01 sec)

解释: FROM中的子句有3个表,分别设置别名 Customers AS COrders AS OOrderItems AS OI 给予子句WHERE引用。

自联结

mysql> SELECT cust_id, cust_name, cust_contact
    -> FROM Customers
    -> WHERE cust_name = (SELECT cust_name
    -> FROM Customers
    -> WHERE cust_contact = 'Jim Jones');
+------------+-----------+--------------------+
| cust_id    | cust_name | cust_contact       |
+------------+-----------+--------------------+
| 1000000003 | Fun4All   | Jim Jones          |
| 1000000004 | Fun4All   | Denise L. Stephens |
+------------+-----------+--------------------+
2 rows in set (0.01 sec)

解释;括号里的SELECT做了一个简单的检索,返回公司的cust_name,给予括号外SELECT查询。

另一个种查询方式

mysql> SELECT c1.cust_id, c1.cust_name, c1.cust_contact
    -> FROM Customers AS c1, Customers AS c2
    -> WHERE c1.cust_name = c2.cust_name
    -> AND c2.cust_contact = 'Jim Jones';
+------------+-----------+--------------------+
| cust_id    | cust_name | cust_contact       |
+------------+-----------+--------------------+
| 1000000003 | Fun4All   | Jim Jones          |
| 1000000004 | Fun4All   | Denise L. Stephens |
+------------+-----------+--------------------+
2 rows in set (0.01 sec)

自然联结

通过对表使用通配符*,对所有其他的表列,使用明确的子集来完成。

mysql> SELECT C.*, O.order_num, O.order_date, OI.prod_id,
    -> OI.quantity, OI.item_price
    -> FROM Customers AS C, Orders AS O, OrderItems AS OI
    -> WHERE C.cust_id = O.cust_id
    -> AND OI.order_num = O.order_num
    -> AND prod_id = 'RGAN01';

解释: *通配符只对第一个表使用,列出其他明确的列。

外部联结

联结包含那些在相关表中没有关联的行的行。

  • 对每个客户下了多少订单进行计算,包括未下单的客户
  • 列出所有产品以及订购数量,包含没有人订购的产品
  • 计算平均销售规模,包括没下单的客户。

检索所有客户及订单,内部联结

mysql> SELECT Customers.cust_id, Orders.order_num
    -> FROM Customers INNER JOIN Orders
    -> ON Customers.cust_id = Orders.cust_id;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 |     20005 |
| 1000000001 |     20009 |
| 1000000003 |     20006 |
| 1000000004 |     20007 |
| 1000000005 |     20008 |
+------------+-----------+
5 rows in set (0.00 sec)

外部联结,检索所有客户,包含那些没有订单的客户。

mysql> SELECT Customers.cust_id, Orders.order_num
    -> FROM Customers LEFT OUTER JOIN Orders
    -> ON Customers.cust_id = Orders.cust_id;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 |     20005 |
| 1000000001 |     20009 |
| 1000000002 |      NULL |
| 1000000003 |     20006 |
| 1000000004 |     20007 |
| 1000000005 |     20008 |
+------------+-----------+
6 rows in set (0.00 sec)

OUTER JOIN 指定联结类型,与内部联结关联两个表中不同的是,外部联结还包含没有关联的行,用 RIGHT与LEFT关键字指定包含其所有行的表是左边还是右边。

使用带聚集函数的联结

检索所有客户及每个客户所下订单

mysql> SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
    -> FROM Customers INNER JOIN Orders
    -> ON Customers.cust_id = Orders.cust_id
    -> GROUP BY Customers.cust_id;
+------------+---------+
| cust_id    | num_ord |
+------------+---------+
| 1000000001 |       2 |
| 1000000003 |       1 |
| 1000000004 |       1 |
| 1000000005 |       1 |
+------------+---------+
4 rows in set (0.02 sec)

解释: INNER JOIN联结CustomersOrders表,GROUP BY子句按客户分组数据,

COUNT(Orders.order_num) 计算客户订单计数。

使用联结条件

  • 主要联结类型,一般使用内部联结
  • 不同的DBMS联结方式不同。
  • 保证使用正确的联结条件
  • 使用多个联结,先分别测试每个联结。

创建高级链接-左连接&&右链接

在自己做项目的过程中,遇到了相关的数据库的查询的问题,在这里做一下简短的记录和总结
其中左连接和右链接属于外连接:
左连接: left (outer) join
右链接: right (outer) join
外连接的特点是:查询出来结果存在不满足条件的可能

左连接

左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。

select * from Menu1 m1 left join Menu2 m2 on m1.id = m2.id;

img

右连接

右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。

select * from Menu1 m1 right join Menu2 m2 on m1.id = m2.id;

img

内连接-总结

查询结果必须满足条件,返回同时满足两个表的部分

select * from Menu1 m1 inner join Menu2 m2 on m1.id = m2.id;

在这里插入图片描述

举个栗子

已知员工的rid,通过rid去表hr_role中去查询hrid,通过查询到的hrid去表menu_role中去查询mid,最后通过mid查询menu表中的符合条件的项,并且通过parentId和其父级条目平成一个项

在这里插入图片描述

目前的有两种想法:
(1)通过右连接 加 子查询:

select * from menu as m1 
inner join 
(select id id2, component component2,  name name2, iconCls iconCls2, keepAlive keepAlive2, requireAuth requireAuth2, parentId parentId2, Enabled enabled2, path path2 from menu where menu.id in 
(select mid from menu_role where menu_role.rid in 
(select rid from hr_role where hr_role.hrid = 10))) 
as m2 
on m1.id = m2.parentId2 ;

2)通过笛卡尔积的方式,再加上需要的条件:

select distinct m1.*,m2.`id` as id2,m2.`component` as component2,m2.`enabled` as enabled2,m2.`iconCls` as iconCls2,m2.`keepAlive` as keepAlive2,m2.`name` as name2,m2.`parentId` as parentId2,m2.`requireAuth` as requireAuth2,m2.`path` as path2 
from menu m1,menu m2,hr_role hrr,menu_role mr 
where m1.`id`=m2.`parentId` and hrr.`hrid`= 10 and hrr.`rid`=mr.`rid` and mr.`mid`=m2.`id` and m2.`enabled`=true 
order by m1.`id`,m2.`id`

补充

笛卡尔积:没有连接条件的表关系返回的结果是笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

组合查询

如何用UNION操作符将多条SELECT语句组合成一个查询

组合查询

  • 并(union) 执行多个查询并将结果作为单个查询结果返回。

一般需要使用组合查询的情况

  • 单个查询中从不同的表类似返回结果数据
  • 单个表执行多个查询,按单个查询返回数据

创建组合查询

检索 IL,IN,MI几个洲的客户报表。

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_state IN ('IL', 'IN', 'MI');
+---------------+--------------+-----------------------+
| cust_name     | cust_contact | cust_email            |
+---------------+--------------+-----------------------+
| Village Toys  | John Smith   | [email protected] |
| Fun4All       | Jim Jones    | [email protected]    |
| The Toy Store | Kim Howard   | NULL                  |
+---------------+--------------+-----------------------+
3 rows in set (0.01 sec)

SELECT利用=符合,检索出所有Fun4All单位

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_name = 'Fun4All';
+-----------+--------------------+-----------------------+
| cust_name | cust_contact       | cust_email            |
+-----------+--------------------+-----------------------+
| Fun4All   | Jim Jones          | [email protected]    |
| Fun4All   | Denise L. Stephens | [email protected] |
+-----------+--------------------+-----------------------+
2 rows in set (0.00 sec)

把上面两条语句进行组合

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_state IN ('IL','IN','MI')
    -> UNION
    -> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_name = 'Fun4All';
+---------------+--------------------+-----------------------+
| cust_name     | cust_contact       | cust_email            |
+---------------+--------------------+-----------------------+
| Village Toys  | John Smith         | [email protected] |
| Fun4All       | Jim Jones          | [email protected]    |
| The Toy Store | Kim Howard         | NULL                  |
| Fun4All       | Denise L. Stephens | [email protected] |
+---------------+--------------------+-----------------------+
4 rows in set (0.02 sec)

解释: 中介有UNION分割开,并把输出组合成儿一个查询结果

另一个检索

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_state IN('IL','IN','MI')
    -> OR cust_name = 'Fun4All';
+---------------+--------------------+-----------------------+
| cust_name     | cust_contact       | cust_email            |
+---------------+--------------------+-----------------------+
| Village Toys  | John Smith         | [email protected] |
| Fun4All       | Jim Jones          | [email protected]    |
| Fun4All       | Denise L. Stephens | [email protected] |
| The Toy Store | Kim Howard         | NULL                  |
+---------------+--------------------+-----------------------+
4 rows in set (0.00 sec)

使用UNION规则

  • 必须有两条以上SELECT语句组合,语句直接用关键字UNION分割。
  • UNION中每个查询必须包含相同的列,表单式,聚集函数。
  • 列的数据必须兼容,

是否带有重复行

UNION默认去掉重复行

如果想要所有行,可以使用UNION ALL 而不是UNION。

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_state IN ('IL','IN','MI')
    -> UNION ALL
    -> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_name = 'Fun4All';
+---------------+--------------------+-----------------------+
| cust_name     | cust_contact       | cust_email            |
+---------------+--------------------+-----------------------+
| Village Toys  | John Smith         | [email protected] |
| Fun4All       | Jim Jones          | [email protected]    |
| The Toy Store | Kim Howard         | NULL                  |
| Fun4All       | Jim Jones          | [email protected]    |
| Fun4All       | Denise L. Stephens | [email protected] |
+---------------+--------------------+-----------------------+
5 rows in set (0.00 sec)

与上面例子比多了一行。

对组合查询结果排序

mysql> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_state IN ('IL''IN','MI')
    -> UNION
    -> SELECT cust_name, cust_contact, cust_email
    -> FROM Customers
    -> WHERE cust_name = 'Fun4ALL'
    -> ORDER BY cust_name, cust_contact;
+--------------+--------------------+-----------------------+
| cust_name    | cust_contact       | cust_email            |
+--------------+--------------------+-----------------------+
| Fun4All      | Denise L. Stephens | [email protected] |
| Fun4All      | Jim Jones          | [email protected]    |
| Village Toys | John Smith         | [email protected] |
+--------------+--------------------+-----------------------+
3 rows in set (0.00 sec)

使用视图

如果利用视图来简化执行SQL语句某些操作。

视图

视图是虚拟表,只是在使用时动态检索数据查询。

为什么使用视图函数

  • 重用SQL语句
  • 简化复杂的SQL操作,方便重用
  • 使用表的组成部分而不是全部
  • 包含数据,可以给用于提高表的特定访问权限,而不是整个。
  • 更改数据格式和表示,当需要返回跟底层表的表示格式不同的数据。

创建视图函数后,可以用与表相同的方式利用他们,可以进行SELECT执行操作,过滤,排序数据 将视图结合其他的视图或表,甚至能添加和更新数据。

注意: 知道视图仅仅是用来查看跟存储在别处的数据,本身不包含数据,数据是从其他表检索出来, 更改与添加表中的数据时,视图将返回改变的数据。

视图函数限制规则

  • 表名必须唯一
  • 创建视图函数没有限制数目
  • 有足够的权限
  • 可以利用其他视图中的数据,来查询构造一个新的视图。
  • 视图不能索引,也不能关联默认值

创建视图

CREATE VIEW 语句来创建视图。删除视图用 DROP VIEW viewname;

mysql> 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;
Query OK, 0 rows affected (0.03 sec)

创建一个ProductCustomers的视图,联结三个表,返回已经订购任意产品的客户

mysql> SELECT * FROM ProductCustomers;
+---------------+--------------------+---------+
| cust_name     | cust_contact       | prod_id |
+---------------+--------------------+---------+
| Village Toys  | John Smith         | BR01    |
| Village Toys  | John Smith         | BR03    |
| Village Toys  | John Smith         | BNBG01  |
| Village Toys  | John Smith         | BNBG02  |
| Village Toys  | John Smith         | BNBG03  |
| Fun4All       | Jim Jones          | BR01    |
| Fun4All       | Jim Jones          | BR02    |
| Fun4All       | Jim Jones          | BR03    |
| Fun4All       | Denise L. Stephens | BR03    |
| Fun4All       | Denise L. Stephens | BNBG01  |
| Fun4All       | Denise L. Stephens | BNBG02  |
| Fun4All       | Denise L. Stephens | BNBG03  |
| Fun4All       | Denise L. Stephens | RGAN01  |
| The Toy Store | Kim Howard         | RGAN01  |
| The Toy Store | Kim Howard         | BR03    |
| The Toy Store | Kim Howard         | BNBG01  |
| The Toy Store | Kim Howard         | BNBG02  |
| The Toy Store | Kim Howard         | BNBG03  |
+---------------+--------------------+---------+
18 rows in set (0.01 sec)

检索 ProductCustomers表的数据

mysql> SELECT cust_name, cust_contact
    -> FROM ProductCustomers
    -> WHERE prod_id = 'RGAN01';
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set (0.00 sec)

解释: 用WHERE子句过滤实体中检索的特定数据。

用视图重新格式化检索出的数据

假设经常需要检索下面的语句,为了不用经常执行,把此语句转换为视图。

mysql> SELECT CONCAT(vend_name, ' (', vend_country, ')') AS vend_title FROM Vendors
    -> ORDER BY vend_name;
+-------------------------+
| vend_title              |
+-------------------------+
| Bear Emporium (USA)     |
| Bears R Us (USA)        |
| Doll House Inc. (USA)   |
| Fun and Games (England) |
| Furball Inc. (USA)      |
| Jouets et ours (France) |
+-------------------------+
6 rows in set (0.00 sec)

把上面的语句转成视图

mysql> CREATE VIEW VendorLocations AS SELECT CONCAT(vend_name, ' (', vend_country, ')') AS vend_title FROM Vendors ORDER BY vend_name;
Query OK, 0 rows affected (0.02 sec)

检索新生成的视图表

mysql> SELECT * FROM VendorLocations;
+-------------------------+
| vend_title              |
+-------------------------+
| Bear Emporium (USA)     |
| Bears R Us (USA)        |
| Doll House Inc. (USA)   |
| Fun and Games (England) |
| Furball Inc. (USA)      |
| Jouets et ours (France) |
+-------------------------+
6 rows in set (0.00 sec)

用视图过滤不想要的数据

定一个一个emaillist,需要过滤没有email的邮件地址的客户。

mysql> CREATE VIEW CustomerEMAIList AS
    -> SELECT cust_id, cust_name, cust_email
    -> FROM Customers
    -> WHERE cust_email IS NOT NULL;
Query OK, 0 rows affected (0.03 sec)

解释: 要WHERE 子句过滤没有电子邮箱的客户。

mysql> SELECT * FROM CustomerEMAIList;
+------------+--------------+-----------------------+
| cust_id    | cust_name    | cust_email            |
+------------+--------------+-----------------------+
| 1000000001 | Village Toys | [email protected] |
| 1000000003 | Fun4All      | [email protected]    |
| 1000000004 | Fun4All      | [email protected] |
| 1000000006 | Toy Land     | [email protected]       |
+------------+--------------+-----------------------+
4 rows in set (0.01 sec)

使用视图计算字段

检索订单物品,计算价格

mysql> SELECT prod_id,
    -> quantity,
    -> item_price,
    -> quantity*item_price AS expaned_price
    -> FROM OrderItems
    -> WHERE order_num = 20008;
+---------+----------+------------+---------------+
| prod_id | quantity | item_price | expaned_price |
+---------+----------+------------+---------------+
| RGAN01  |        5 |       4.99 |         24.95 |
| BR03    |        5 |      11.99 |         59.95 |
| BNBG01  |       10 |       3.49 |         34.90 |
| BNBG02  |       10 |       3.49 |         34.90 |
| BNBG03  |       10 |       3.49 |         34.90 |
+---------+----------+------------+---------------+
5 rows in set (0.01 sec)

换成视图

mysql> CREATE VIEW OrderItemsExpandes AS
    -> SELECT order_num,
    -> prod_id,
    -> quantity,
    -> item_price,
    -> quantity*item_price AS expanded_price
    -> FROM OrderItems;
Query OK, 0 rows affected (0.01 sec)

Guess you like

Origin blog.csdn.net/qq_45205390/article/details/121410189