教程链接:Datawhale - 一个热爱学习的社区
视图是一张虚拟的表。《sql基础教程第2版》用一句话非常凝练的概括了视图与表的区别---“是否保存了实际的数据”。
- 通过定义视图可以将频繁使用的SELECT语句保存以提高效率。
- 通过定义视图可以使用户看到的数据更加清晰。
- 通过定义视图可以不对外公开数据表全部字段,增强数据的保密性。
- 通过定义视图可以降低数据的冗余。
创建视图的基本语法是
CREATE VIEW <视图名称>(<列名1>,<列名2>,...) AS
注意:可以在视图的基础上再创建视图;需要注意的是在一般的DBMS中定义视图时不能使用ORDER BY语句,因为视图和表一样,数据行都是没有数据的;
我们也可以创建多表视图,使用WHERE进行条件控制
CREATE VIEW view_shop_product(product_type, sale_price, shop_name)
AS
SELECT product_type, sale_price, shop_name
FROM product,
shop_product
WHERE product.product_id = shop_product.product_id;
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从 MySQL 4.1 开始引入,在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。
与视图的关系:子查询就是将用来定义视图的 SELECT 语句直接用于 FROM 子句当中。其中AS studentSum可以看作是子查询的名称,而且由于子查询是一次性的,所以子查询不会像视图那样保存在存储介质中, 而是在 SELECT 语句执行之后就消失了。
视图和子查询是数据库操作中较为基础的内容,对于一些复杂的查询需要使用子查询加一些条件语句组合才能得到正确的结果。但是无论如何对于一个SQL语句来说都不应该设计的层数非常深且特别复杂,不仅可读性差而且执行效率也难以保证,所以尽量有简洁的语句来完成需要的功能。
CREATE VIEW ViewPractice5_1 AS
SELECT product_name, sale_price, regist_date
FROM product
WHERE sale_price >= 1000
AND regist_date = '2009-09-20';
输入 SELECT * FROM ViewPractice5_1; 检查结果
ViewPractice5_1
中插入如下数据,会得到什么样的结果?为什么?INSERT INTO ViewPractice5_1 VALUES (' 刀子 ', 300, '2009-11-02');
结果
[2023-07-26 14:18:18] [HY000][1423] Field of view 'shop.ViewPractice5_1' underlying table doesn't have a default value
翻译为底层的表没有默认的值,推测因为这个视图底层的表有的列要求非空,而这里给不出值,就不能了。由此也可知道修改视图也会修改底层的表。
SELECT product_id, product_name, sale_price, (SELECT AVG(sale_price) FROM product) AS sale_price_avg
FROM product;
CREATE VIEW AvgPriceByType(product_id,product_name,product_type,sale_price,sale_price_avg_type)
AS
SELECT product_id,product_name,product_type,sale_price,
(SELECT avg(sale_price) FROM product AS pm WHERE pm.product_type = pn.product_type GROUP BY product_type)
AS sale_price_avg_type FROM product AS pn
是的,四则运算中含有NULL,不进行特殊处理,运算结果是必然变成NULL。
product
(商品)表执行如下 2 条 SELECT
语句,能够得到什么样的结果呢SELECT product_name, purchase_price
FROM product
WHERE purchase_price NOT IN (500, 2800, 5000);
返回product_name和purchase_price两列,行的数据满足其原本在product表中的purchase_price不是500,2800,500和NULL。
SELECT product_name, purchase_price
FROM product
WHERE purchase_price NOT IN (500, 2800, 5000, NULL);
NULL不等于任何值,无法判断即使不是500,2800,5000的那些值是否为NULL。
可以用NOT EXISTS字句来查找,因为在子查询中使用等于操作符时,NULL 值将被视为与其他 NULL 值不相等。例如:
SELECT * FROM mytable WHERE NOT EXISTS (SELECT * FROM mytable2 WHERE mytable2.col1 = mytable.col1);
SELECT SUM(CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END) AS low_price,
SUM(CASE WHEN sale_price BETWEEN 1001 AND 3000 THEN 1 ELSE 0 END ) AS mid_price,
SUM(CASE WHEN sale_price >= 3001 THEN 1 ELSE 0 END) AS high_price
FROM product;
结果