Skip to content

PostgreSQL 视图

概述

视图(View)是基于 SQL 查询结果定义的虚拟表。视图本身不存储数据,而是在每次查询时动态执行其定义的 SQL 语句。视图的主要用途包括简化复杂查询、提供数据访问安全控制,以及为应用程序提供稳定的数据接口。

创建视图

使用 CREATE VIEW 语句创建视图:

sql
-- 创建简单视图:筛选活跃用户
CREATE VIEW active_users AS
SELECT * FROM users WHERE status = 'active';

-- 创建复杂视图:用户消费汇总
CREATE VIEW user_summary AS
SELECT
    u.id,
    u.name,
    u.email,
    COUNT(o.id) AS order_count,
    COALESCE(SUM(o.total), 0) AS total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;

使用 CREATE OR REPLACE VIEW 可以在视图已存在时更新其定义:

sql
-- 创建或替换视图
CREATE OR REPLACE VIEW active_users AS
SELECT id, name, email, created_at
FROM users
WHERE status = 'active';

使用视图

视图的使用方式与普通表完全相同:

sql
-- 查询视图
SELECT * FROM active_users;

-- 在视图上添加过滤条件
SELECT * FROM user_summary WHERE total_spent > 1000;

-- 视图可以与其他表进行连接
SELECT
    a.name,
    a.email,
    p.product_name
FROM active_users a
JOIN orders o ON a.id = o.user_id
JOIN products p ON o.product_id = p.id;

可更新视图

满足以下条件的简单视图支持 INSERTUPDATEDELETE 操作:

  • 视图基于单个表
  • 不包含聚合函数、DISTINCTGROUP BYHAVINGUNION
  • 不包含子查询
sql
-- 创建可更新视图
CREATE VIEW simple_users AS
SELECT id, name, email FROM users;

-- 通过视图插入数据
INSERT INTO simple_users (id, name, email)
VALUES (1, 'John', 'john@example.com');

-- 通过视图更新数据
UPDATE simple_users SET name = 'Jane' WHERE id = 1;

-- 通过视图删除数据
DELETE FROM simple_users WHERE id = 1;

WITH CHECK OPTION

使用 WITH CHECK OPTION 可以防止通过视图插入或更新不符合视图条件的数据:

sql
-- 创建带检查选项的视图
CREATE VIEW active_users AS
SELECT * FROM users WHERE status = 'active'
WITH CHECK OPTION;

-- 以下操作会失败,因为插入的数据不满足 status = 'active' 条件
INSERT INTO active_users (id, name, status)
VALUES (2, 'Bob', 'inactive');  -- 错误!

物化视图

物化视图(Materialized View)与普通视图不同,它会将查询结果实际存储在磁盘上,适合计算量大但数据更新不频繁的场景:

sql
-- 创建物化视图:按月统计销售数据
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT
    DATE_TRUNC('month', created_at) AS month,
    COUNT(*) AS order_count,
    SUM(total) AS revenue
FROM orders
GROUP BY DATE_TRUNC('month', created_at);

-- 刷新物化视图(全量刷新,会锁表)
REFRESH MATERIALIZED VIEW monthly_sales;

-- 并发刷新(不会锁定查询,需要唯一索引)
REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_sales;

提示

使用 CONCURRENTLY 选项进行并发刷新时,物化视图上必须有唯一索引。

删除视图

sql
-- 删除视图
DROP VIEW active_users;

-- 删除视图(如果存在)
DROP VIEW IF EXISTS old_view;

-- 级联删除(同时删除依赖该视图的对象)
DROP VIEW user_summary CASCADE;

-- 删除物化视图
DROP MATERIALIZED VIEW monthly_sales;

小结

视图要点:

  • 视图是基于查询定义的虚拟表,不实际存储数据
  • 简化复杂查询,提供数据安全控制
  • 简单视图可以执行插入、更新、删除操作
  • WITH CHECK OPTION 确保通过视图修改的数据始终符合视图条件
  • 物化视图将结果缓存到磁盘,适合计算密集型查询,需手动刷新