下面讲 SQL 视图的创建、修改和可更新视图的用法,跟着注释一步步来。
学习内容
- 创建视图
- 用 CREATE VIEW 把查询打包,方便反复用,就像给复杂查询取个名字。
- 视图不存数据,存的是查询定义,执行时才从基表拉数据。
- 可以当表查,还能跟其他表连起来用。
- 修改视图
- 要改视图?直接删了重来,DROP VIEW 然后 CREATE VIEW。
- 或者用 CREATE OR REPLACE VIEW,一步到位,省事。
- 可更新视图
- 只能基于单表,不能有 JOIN、UNION 这种花里胡哨的操作。
- 不能用 DISTINCT、GROUP BY、HAVING 或聚合函数(像 SUM、AVG)。
- SELECT 里不能有子查询。
- 基表里所有 NOT NULL 列得在视图里(为了支持 INSERT)。
- 有些视图能直接改基表数据,但得满足条件:
- 能干啥?可以 UPDATE 或 DELETE 基表数据。
- WITH CHECK OPTION
- 视图有筛选条件(比如 WHERE),更新后得确保数据还符合这条件。
- WITH CHECK OPTION 就像个门卫,拦住不符合条件的更新,防止数据“跑偏”。
示例代码与讲解
1. 创建视图
SELECT
client_id,
name,
SUM(invoice_total) AS total_sales
FROM clients c
JOIN invoices USING (client_id)
GROUP BY client_id, name;
- 这是个查询,算每个客户的总销售,挺常用的。
CREATE VIEW sales_by_client AS
SELECT
client_id,
name,
SUM(invoice_total) AS total_sales
FROM clients c
JOIN invoices USING (client_id)
GROUP BY client_id, name;
- 给上面查询包个视图,叫 sales_by_client。跑这代码没输出,但会在数据库里存个视图。像这样:
SELECT *
FROM sales_by_client
ORDER BY total_sales DESC;
- 直接查视图,销售总额从高到低排。
SELECT *
FROM sales_by_client
JOIN clients USING (client_id);
- 视图还能跟其他表连,就像普通表一样。
2. 修改视图
DROP VIEW sales_by_client;
- 视图不想要了?直接删。
CREATE OR REPLACE VIEW client_balance AS
SELECT
client_id,
name,
SUM(invoice_total - payment_total) AS Balance
FROM clients
JOIN invoices USING (client_id)
GROUP BY client_id, name;
- 改视图直接用 CREATE OR REPLACE,这里搞了个新视图,算客户欠款余额。
3. 可更新视图
CREATE OR REPLACE VIEW invoices_with_balance AS
SELECT
invoice_id,
number,
client_id,
invoice_total,
payment_total,
invoice_total - payment_total AS Balance,
invoice_date,
due_date,
payment_date
FROM invoices
WHERE invoice_total - payment_total > 0;
- 这个视图列出还没付清的发票(Balance > 0)。
- 它没用 JOIN、聚合函数啥的,满足可更新条件,能直接改基表数据。
DELETE FROM invoices_with_balance
WHERE invoice_id = 1;
- 删掉 invoice_id = 1 的发票,基表也跟着变。
UPDATE invoices_with_balance
SET due_date = DATE_ADD(due_date, INTERVAL 2 DAY)
WHERE invoice_id = 2;
- 把 invoice_id = 2 的截止日期推迟 2 天。
4. WITH CHECK OPTION
UPDATE invoices_with_balance
SET invoice_total = payment_total
WHERE invoice_id = 2;
- 想把 invoice_id = 2 的 invoice_total 改成 payment_total,结果 Balance 变 0,不符合视图的 Balance > 0,这行就直接没了。
CREATE OR REPLACE VIEW invoices_with_balance1 AS
SELECT
invoice_id,
number,
client_id,
invoice_total,
payment_total,
invoice_total - payment_total AS Balance,
invoice_date,
due_date,
payment_date
FROM invoices
WHERE invoice_total - payment_total > 0
WITH CHECK OPTION;
- 加上 WITH CHECK OPTION,视图多了一道防线。
UPDATE invoices_with_balance1
SET invoice_total = payment_total
WHERE invoice_id = 3;
- 再试着改 invoice_id = 3,因为 Balance 会变 0,违反视图条件,直接报错,不让你改。
作业
1. 创建视图
CREATE VIEW client_balance AS
SELECT
client_id,
name,
SUM(invoice_total - payment_total) AS Balance
FROM clients
JOIN invoices USING (client_id)
GROUP BY client_id, name;
- 搞个视图,算每个客户欠多少钱。
总结
讲了怎么创建视图、改视图,还弄了可更新视图,带上 WITH CHECK OPTION 防跑偏。用的 sql_invoicing 数据库。接下来看存储过程和触发器。
| Austin Liu 刘恒辉 Project Manager and Software Designer E-Mail:lzhdim@163.com Blog:https://lzhdim.cnblogs.com 欢迎收藏和转载此博客中的博文,但是请注明出处,给笔者一个与大家交流的空间。谢谢大家。 |
