熟悉SQL的CRUD后,是时候来提高SQL能力了。
本文重点是学习视图和子查询,这两者可以跟表一样进行使用,因此恰当地运用他们可以写出更灵活的SQL语句。
Views are stored queries that when invoked produce a
result set. A view acts as a virtual table. 视图保存了查询语句,当调用视图时会产生一个结果集。视图充当了虚拟表的角色。
——来自MySQL官方文档Chapter24.5 Using Views
视图和表的区别
视图的优点:
!注意:性能问题
每次调用视图时它实际上会执行查询操作,如果使用多个连接和过滤创建了复杂的视图或者嵌套了视图,性能可能会下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行性能上的测试。
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
创建测试表product
CREATE TABLE product(
product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INTEGER,
purchase_price INTEGER,
regist_date DATE,
PRIMARY KEY(product_id)
);
START TRANSACTION;
INSERT INTO product VALUES('0001', 'T恤衫', '衣服', 1000, 50, '2020-09-20');
INSERT INTO product VALUES('0002', '打孔器', '办公用品', 1000, 32, '2020-09-20');
INSERT INTO product VALUES('0003', '运动T恤', '衣服', 1000, 280, '2020-09-20');
INSERT INTO product VALUES('0004', '菜刀', '厨房用具', 1000, 500, '2020-09-20');
INSERT INTO product VALUES('0005', '高压锅', '厨房用具', 1000, 680, '2020-09-20');
INSERT INTO product VALUES('0006', '叉子', '厨房用具', 1000, 5, '2020-09-20');
INSERT INTO product VALUES('0007', '擦菜板', '厨房用具', 1000, 88, '2020-09-20');
INSERT INTO product VALUES('0008', '圆珠笔', '衣服', 1000, 10, '2020-09-20');
COMMIT;
创建视图
CREATE VIEW productsum(product_type, cnt_product)
AS
SELECT product_type,COUNT(*)
FROM product
GROUP BY product_type;
查看某个具体的视图
SELECT * FROM productsum;
查看某个数据库下的所有视图:
方法一:通过状态的COMMENT
列来查找:
说明:Mysql5.1支持视图,视图被看作一种抽象表,因此显示视图状态的语句与显示表状态的语句相同,只是在
COMMENT
列中以view
区分
SHOW TABLE STATUS WHERE COMMENT='VIEW';
方法二:通过系统表information_schema.tables
查询
SELECT * FROM information_schema.tables
WHERE table_schema='yourDatabaseName' AND table_type='VIEW';
DROP VIEW view_name;
ORDER BY
子句标准SQL中有这样的规定:如果定义视图的SELECT
语句能够满足某些条件,那么这个视图就可以被更新,下面列举一些比较具有代表性的条件;
SELECT
子句中未使用DESINCT
FROM
子句中只有一张表GROUP BY
子句HAVING
子句视图归根结底还是从表派生出来的,如果原表可以更新,那么视图中的数据也可以更新,反之亦然,视图中的数据可以更新,那么原表的数据也可以更新。如果视图发生了改变,而原表没有进行相应更新的话,就无法保证数据的一致性了。
创建一视图,这个视图可以满足更新的条件
CREATE VIEW productjim(product_id, product_name, product_type, sale_price, purchase_price, regist_date)
AS
SELECT *
FROM product
WHERE product_type='办公用品';
在视图中插入一组数据
INSERT INTO productjim VALUES('0009','印章','办公用品',95,10,'2020-11-30');
查询该视图
SELECT * FROM productjim;
子查询也可以看做是一张一次性的视图
=
、>
、<
这样的比较运算符中,这也正是标量子查询的优势所在。假设我们需要在product
表中查询这样的表:
“查询出购买高于平均购买价的商品”
我们一开始可能会考虑这样的SQL语句
SELECT *
FROM product
WHERE purchase_price > AVG(purchase_price);
很可惜,WHERE子句不能使用聚合函数,所以该语句会报错,这时我们可以使用子查询:
SELECT *
FROM product
WHERE purchase_price >(
SELECT AVG(purchase_price)
FROM product
);
关联子查询比较诡异,知乎上有一篇讲得很好的文章,在此贴上简单易懂教你学会SQL关联子查询