Oracle视图 #

一、视图概述 #

1.1 什么是视图 #

视图是一个或多个表的逻辑表示,它存储查询定义而不存储数据。视图可以简化复杂查询、提供数据安全性和逻辑数据独立性。

text
视图类型
├── 简单视图
│   └── 基于单个表,无函数
├── 复杂视图
│   └── 多表连接,包含函数
├── 可更新视图
│   └── 允许DML操作
└── 只读视图
    └── 不允许DML操作

二、创建视图 #

2.1 基本语法 #

sql
-- 创建视图基本语法
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name
    [(alias1, alias2, ...)]
AS
SELECT statement
[WITH CHECK OPTION [CONSTRAINT constraint_name]]
[WITH READ ONLY];

2.2 创建简单视图 #

sql
-- 创建简单视图
CREATE OR REPLACE VIEW emp_view AS
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE department_id = 10;

-- 使用视图
SELECT * FROM emp_view;

-- 创建带别名的视图
CREATE OR REPLACE VIEW emp_view (
    emp_id, emp_name, emp_salary
) AS
SELECT employee_id, first_name || ' ' || last_name, salary
FROM employees
WHERE department_id = 10;

2.3 创建复杂视图 #

sql
-- 创建多表连接视图
CREATE OR REPLACE VIEW emp_dept_view AS
SELECT 
    e.employee_id,
    e.first_name,
    e.last_name,
    e.salary,
    d.department_name,
    l.city
FROM employees e
JOIN departments d ON e.department_id = d.department_id
JOIN locations l ON d.location_id = l.location_id;

-- 创建包含聚合函数的视图
CREATE OR REPLACE VIEW dept_stats_view AS
SELECT 
    department_id,
    COUNT(*) AS employee_count,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    MIN(salary) AS min_salary
FROM employees
GROUP BY department_id;

三、可更新视图 #

3.1 可更新视图条件 #

sql
-- 可更新视图条件:
-- 1. 不包含聚合函数
-- 2. 不包含DISTINCT
-- 3. 不包含GROUP BY
-- 4. 不包含集合运算
-- 5. 不包含ROWNUM伪列

-- 创建可更新视图
CREATE OR REPLACE VIEW emp_update_view AS
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE department_id = 10;

-- 通过视图插入
INSERT INTO emp_update_view VALUES (999, 'Test', 'User', 5000);

-- 通过视图更新
UPDATE emp_update_view SET salary = 6000 WHERE employee_id = 999;

-- 通过视图删除
DELETE FROM emp_update_view WHERE employee_id = 999;

3.2 WITH CHECK OPTION #

sql
-- WITH CHECK OPTION:确保DML操作后的数据仍在视图中
CREATE OR REPLACE VIEW emp_dept_10_view AS
SELECT employee_id, first_name, last_name, salary, department_id
FROM employees
WHERE department_id = 10
WITH CHECK OPTION;

-- 允许:更新后仍在视图中
UPDATE emp_dept_10_view SET salary = 6000 WHERE employee_id = 100;

-- 不允许:更新后不在视图中
UPDATE emp_dept_10_view SET department_id = 20 WHERE employee_id = 100;
-- ORA-01402: view WITH CHECK OPTION where-clause violation

3.3 WITH READ ONLY #

sql
-- 创建只读视图
CREATE OR REPLACE VIEW emp_readonly_view AS
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE department_id = 10
WITH READ ONLY;

-- 不允许DML操作
-- INSERT INTO emp_readonly_view VALUES (999, 'Test', 'User', 5000);
-- ORA-42399: cannot perform a DML operation on a read-only view

四、视图管理 #

4.1 查看视图 #

sql
-- 查看视图定义
SELECT view_name, text FROM user_views;

-- 查看视图详细信息
SELECT * FROM user_views WHERE view_name = 'EMP_VIEW';

-- 查看视图列
SELECT column_name, data_type, nullable
FROM user_tab_columns
WHERE table_name = 'EMP_VIEW';

-- 使用DESC命令
DESC emp_view;

4.2 修改视图 #

sql
-- 使用CREATE OR REPLACE修改视图
CREATE OR REPLACE VIEW emp_view AS
SELECT employee_id, first_name, last_name, salary, hire_date
FROM employees
WHERE department_id = 10;

4.3 删除视图 #

sql
-- 删除视图
DROP VIEW emp_view;

-- 删除不存在的视图(避免错误)
DROP VIEW IF EXISTS emp_view;

五、内联视图 #

5.1 内联视图使用 #

sql
-- 内联视图:FROM子句中的子查询
SELECT e.employee_id, e.first_name, d.department_name
FROM (
    SELECT employee_id, first_name, department_id
    FROM employees
    WHERE salary > 10000
) e
JOIN departments d ON e.department_id = d.department_id;

-- 使用内联视图进行分页
SELECT *
FROM (
    SELECT e.*, ROWNUM rn
    FROM (
        SELECT * FROM employees ORDER BY salary DESC
    ) e
    WHERE ROWNUM <= 10
)
WHERE rn > 5;

六、视图最佳实践 #

6.1 视图命名规范 #

sql
-- 推荐:使用v_或view_前缀
CREATE OR REPLACE VIEW v_employee_details AS ...
CREATE OR REPLACE VIEW view_dept_stats AS ...

6.2 视图使用场景 #

sql
-- 1. 简化复杂查询
CREATE OR REPLACE VIEW v_emp_full_info AS
SELECT e.*, d.department_name, l.city
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
LEFT JOIN locations l ON d.location_id = l.location_id;

-- 2. 数据安全
CREATE OR REPLACE VIEW v_emp_public AS
SELECT employee_id, first_name, last_name
FROM employees;  -- 隐藏敏感列如salary

-- 3. 业务逻辑封装
CREATE OR REPLACE VIEW v_active_employees AS
SELECT * FROM employees
WHERE status = 'ACTIVE' AND hire_date <= SYSDATE;

七、总结 #

视图要点:

类型 特点 DML支持
简单视图 单表,无函数 支持
复杂视图 多表,有函数 受限
只读视图 WITH READ ONLY 不支持

最佳实践:

  1. 视图用于简化查询和封装逻辑
  2. 注意可更新视图的限制
  3. 使用WITH CHECK OPTION保证数据一致性
  4. 避免嵌套过多视图
  5. 定期检查视图依赖关系

下一步,让我们学习物化视图!

最后更新:2026-03-27