在 Oracle 数据库中,视图(View)是一种虚拟表,它基于 SQL 查询语句从一个或多个表(或其他视图)中导出数据。视图并不存储实际数据,而是动态呈现数据的逻辑结构,提供了数据抽象、安全控制和简化查询的强大功能。
一、视图的基本概念
1. 定义与特性
虚拟表:视图是存储在数据字典中的 SQL 查询定义,不占用物理存储空间。
动态数据:视图的数据随基表(Base Table)的变化而实时更新。
安全性:通过视图可以限制用户对敏感数据的访问权限。
简化查询:复杂查询可以封装为视图,供用户直接调用。
2. 视图的用途
数据抽象:隐藏表的复杂结构,提供简洁的数据接口。
权限控制:仅暴露用户需要的数据列,保护敏感信息(如工资、密码)。
跨表查询:将多表连接查询封装为视图,简化客户端使用。
兼容旧系统:通过视图为表结构变更提供向后兼容能力。
二、视图的分类
Oracle 视图可分为以下几类:
1. 简单视图(Simple View)
特点:基于单个表,不包含函数、分组或连接操作。
支持操作:可进行 DML 操作(INSERT/UPDATE/DELETE),需满足一定条件。
-- 创建简单视图
CREATE VIEW emp_dept_view AS
SELECT employee_id, first_name, department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;2. 复杂视图(Complex View)
特点:包含函数、分组(GROUP BY)、连接(JOIN)或聚合操作(如 SUM、COUNT)。
限制:通常不支持 DML 操作。
-- 创建复杂视图(含聚合函数)
CREATE VIEW dept_salary_view AS
SELECT
d.department_name,
COUNT(e.employee_id) AS employee_count,
AVG(e.salary) AS avg_salary
FROM
employees e
JOIN
departments d ON e.department_id = d.department_id
GROUP BY
d.department_name;3. 物化视图(Materialized View)
特点:预计算并存储视图结果,定期刷新,适用于数据仓库环境。
优势:提高复杂查询性能,减少实时计算开销。
-- 创建物化视图
CREATE MATERIALIZED VIEW emp_salary_mv
BUILD IMMEDIATE -- 立即构建
REFRESH COMPLETE ON DEMAND -- 按需完全刷新
AS
SELECT
department_id,
SUM(salary) AS total_salary,
COUNT(*) AS employee_count
FROM
employees
GROUP BY
department_id;4. 内嵌视图(Inline View)
特点:在 SQL 查询的 FROM 子句中定义的临时视图,也称为子查询。
用途:简化复杂查询,提高可读性。
-- 使用内嵌视图过滤数据
SELECT
e.employee_id,
e.first_name,
d.dept_name
FROM
employees e
JOIN (
SELECT department_id, department_name AS dept_name
FROM departments
) d ON e.department_id = d.department_id;三、视图的创建与管理
1. 创建视图
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name [(column_alias[, ...])]
AS
SELECT_statement
[WITH CHECK OPTION [CONSTRAINT constraint_name]]
[WITH READ ONLY [CONSTRAINT constraint_name]];关键参数:
OR REPLACE:如果视图已存在,则覆盖原定义。FORCE:即使基表不存在也创建视图(需在基表创建后才能使用)。WITH CHECK OPTION:限制通过视图进行的 DML 操作必须满足视图定义的条件。WITH READ ONLY:禁止通过视图执行 DML 操作。
2. 修改视图
-- 使用OR REPLACE子句重新创建视图
CREATE OR REPLACE VIEW emp_dept_view AS
SELECT employee_id, first_name, last_name, department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;3. 删除视图
DROP VIEW emp_dept_view;4. 查看视图定义
-- 查询数据字典获取视图定义
SELECT text FROM dba_views WHERE view_name = 'EMP_DEPT_VIEW';四、视图的 DML 操作限制
1. 简单视图的 DML 支持
简单视图通常可执行 DML 操作,但需满足以下条件:
视图中的每列必须映射到基表的列。
基表的主键列必须包含在视图中。
视图定义中不包含聚合函数、GROUP BY、DISTINCT 等。
2. WITH CHECK OPTION 约束
-- 创建带CHECK OPTION的视图
CREATE VIEW emp_sales_view AS
SELECT employee_id, first_name, department_id
FROM employees
WHERE department_id = 80 -- 销售部门
WITH CHECK OPTION;
-- 尝试插入非销售部门数据将失败
INSERT INTO emp_sales_view (employee_id, first_name, department_id)
VALUES (1001, 'John', 90); -- 违反CHECK OPTION约束3. 复杂视图的 DML 限制
复杂视图通常不支持 DML 操作,但以下情况除外:
使用 INSTEAD OF 触发器处理复杂视图的 DML 操作。
视图定义满足 Oracle 的 "可更新连接视图" 规则。
五、视图的安全应用
列级权限控制:
-- 创建仅暴露部分列的视图
CREATE VIEW emp_public_view AS
SELECT employee_id, first_name, last_name, job_title
FROM employees;行级权限控制:
-- 创建基于部门的行级安全视图
CREATE VIEW dept_emp_view AS
SELECT *
FROM employees
WHERE department_id = SYS_CONTEXT('USERENV', 'DEPARTMENT_ID');
敏感数据掩码:
-- 创建隐藏部分信息的视图
CREATE VIEW emp_sensitive_view AS
SELECT
employee_id,
first_name,
last_name,
RPAD(SUBSTR(email, 1, 3), LENGTH(email), '*') AS masked_email, -- 邮箱掩码
CASE
WHEN SYSDATE - hire_date > 365 THEN salary -- 老员工可见完整工资
ELSE '*****'
END AS salary
FROM employees;