创建视图
sql
复制代码
USE sql_invoicing; CREATE VIEW sales_by_client AS SELECT client_id, name, SUM(invoice_total) AS total_sales FROM clients c JOIN invoices i USING(client_id) GROUP BY client_id, name;
使用create view ... as
可以创建一个视图
注意:视图不存储数据,数据存储在原本的表中表中。可以完全当成一张表的执行各种操作,但是和一张存储数据的表不等价
sql
复制代码
CREATE VIEW clients_balance AS SELECT client_id, name, SUM(invoice_total - payment_total) AS balance FROM clients c JOIN invoices i USING(client_id) GROUP BY client_id, name;
2 | Myworks | 50.89 |
5 | Topiclounge | 767.63 |
3 | Yadel | 481.35 |
1 | Vinte | 728.34 |
更改或者删除视图
- 先删除再重建
sql
复制代码
USE sql_invoicing; DROP VIEW IF EXISTS clients_balance; -- 若不存在这个视图,直接 DROP 会报错,所以要加上 IF EXISTS 先检测有没有这个视图 CREATE VIEW clients_balance AS …… ORDER BY balance DESC
- 通过工具修改,workbench 或者保存好视图的 sql 文件
可更新视图
sql
复制代码
CREATE OR REPLACE VIEW ... AS
如果一个视图的原始查询语句中没有如下元素:
- DISTINCT 去重
- GROUP BY/HAVING/聚合函数 (后两个通常是伴随着 GROUP BY 分组出现的)
- UNION 纵向连接
则该视图是可更新视图(Updatable Views),可以增删改,否则只能查。
另外,增(INSERT)还要满足附加条件:视图必须包含底层原表的所有必须字段
总之,一般通过原表修改数据,但当出于安全考虑或其他原因没有某表的直接权限时,可以通过视图来修改底层数据(?),前提是视图是可更新的。
sql
复制代码
USE sql_invoicing; CREATE OR REPLACE VIEW invoices_with_balance AS SELECT /* 这里有个小技巧,要插入表中的多列列名时, 可从左侧栏中连选并拖入相关列 */ invoice_id, number, client_id, invoice_total, payment_total, invoice_date, invoice_total - payment_total AS balance, -- 新增列 due_date, payment_date FROM invoices WHERE (invoice_total - payment_total) > 0; /* 这里不能用列别名balance,会报错说不存在, 必须用原列名的表达式,这还是执行顺序的问题 之前讲WHERE和HAVING作为事前筛选和事后筛选的区别时提到过 */ delete from invoices_with_balance where invoice_id = 1; update invoices_with_balance set due_date = date_add(due_date, interval 2 day) where invoice_id = 2
WITH OPTION CHECK
在视图的原始查询语句最后加上 WITH CHECK OPTION
可以防止执行那些会让视图中某些行(记录)消失的修改语句。
sql
复制代码
USE sql_invoicing; CREATE OR REPLACE VIEW invoices_with_balance AS SELECT * FROM invoices WHERE (invoice_total - payment_total) > 0 with check option; delete from invoices_with_balance where invoice_id = 2; -- 失败,无法删除
sql
复制代码
UPDATE invoices_with_balance SET payment_total = invoice_total WHERE invoice_id = 3 -- 还是失败,因为这里修改了之后,这条语句不满足这个视图的条件会消失,所以这个条件可以阻止它运行 -- Error Code: 1369. CHECK OPTION failed 'sql_invoicing.invoices_with_balance'
视图优点总结
- 简化查询
- 增加抽象层,减少数据库设计改动的影响视图给表增加了一个抽象层(模块化),这样如果数据库设计改变了(如一个字段从一个表转移到了另一个表),只需修改视图的查询语句使其能保持原有查询结果即可,不需要修改使用这个视图的查询。 相反,如果没有视图这一层的话,所有查询将直接使用指向原表的原始查询语句,这样一旦更改原表设计,就要相应地更改所有的这些查询。
- 限制对基础表的访问,加强数据安全性在视图中可以对原表的行和列进行筛选,这样如果你禁止了对原始表的访问权限,用户只能通过视图来修改数据,他们就无法修改视图中未返回的那些字段和记录。但注意这通常并不简单,需要良好的规划,否则最后可能搞得一团乱。