视图是各种数据库的通用概念,用户可以像操作表一样操作视图,视图不占用数据库额外的存储空间,而只存储定义
视图是由已存在的数据,通过一定的运算规则,来获得新的数据集合。使用户可以更加灵活的自定义数据集合。视图同时为数据安全性提供了一种控制策略。
创建关系视图
create view 视图名称 as 查询语句|关系运算
create view vw_employees as select employee_id,employee_name,employee_position from employees
利用视图可以用sql增删改查,如果修改了视图的数据,对应的表的数据也会修改。但不是所有的修改都会成功
修改/删除视图
create or replace view 视图名称 as 查询语句|关系运算
删除视图
drop view 视图名
只读视图
create or replace view 视图名称 as 查询语句|关系运算 with read only
只读视图仅支持查询
联接视图
其数据源来源于多个表
create or replace view vw_employee_salary as select e.employee_id,e.employee_name,s.month,s.salary from employees e,salary s where e.employee_id=s.employee_id
强制创建视图
如果视图的基础表没创建,使用强制创建,用force
create or replace force view 视图名称 as 查询语句|关系运算
创建视图约束
with check option仅在视图定义中含有where子句的情况下起作用
with check option可以保证视图数据的完整性
修改视图的定义-只选择员工ID大于3的记录
create or replace view vw_employees as select employee_id,employee_name,employee_position from employees where employee_id>3 with check option
此时这个视图仅包含employee_id>3的记录、此时尝试将任意记录的employee_id修改为3,都会报错
with check option仅对insert、update的操作有限制
with check option实际创建了一个约束
内嵌视图
内嵌视图也是查询定义。内嵌的意义在于,视图定义嵌入在复杂的查询语句中,其角色与普通数据表或关系视图相同。内嵌视图不必使用create view 进行创建。内嵌视图是子查询的一种,可以与数据表、视图一样作为查询语句的数据源存在,但在形式上有较大区别。
获取年龄最小的2名员工。
select * from employees where rownum<3 order by employee_age
结果与预期不符,这是因为rownum对各记录赋予行号的时候,还没有进行排序,也就是rownum早于order by。正确语句如下:
select * from (select * from employees order by employee_age) where rownum<3;
(select * from employees order by employee_age)就是内嵌视图。可以给内嵌视图使用别名,方便使用
select t.employee_id,t.employee_name,t.employee_age,s.salary from (select * from (select * from employees order by employee_age) where rownum<3) t,aslary s where t.employee_id=s.employee)id
内嵌视图优点:节省数据库资源,不增加维护成本;
缺点:不可复用,大数据量的查询效率低
对象视图
对象简介
Oracle中的对象类型与对象
自定义一个对象类型
create or reolace type discount_price_obj as object(attribute1 datatype1,attribute2,datatype2... member funciton funciton1,...member procedure procedurel,...)
create or reolace type discount_price_obj用于创建一个新的类型;as object 代表新类型继承自object;attribute1,attribute2定义对象类型所拥有的属性;datatype1,datatype2,定义属性的数据类型;members function 定义成员函数;member procedure 定义成员
从对象到数据
Oracle的对象类型可以用来定义表结构
create table tmp_employee of employee
create table tmp_employee用于创建新表,of employee表示表的结构来源于对象类型employee
对象类型的实例是对象,而数据表实际存储的是数据。因此每个对象实例都可以映射为表中的某条记录。在Oracle中,可以首先创建对象,然后直接将对象插入到表中
declare e employee;
begin
e:=employee(1,'王五','sqa');
insert into tmp_employee values(e);
end;
注意:只有利用对象类型创建的表才可以向表中插入对象,否则会报错哦
从数据到对象
表中的数据同样可以映射为对象实例
declare e employee;
begin
select value(t) into e from tmp_employee t where employee_id=1;
e.employee_id:=e.employee_id+1;
insert into tmp_employee values(e);
end;
select value(t) into e from tmp_employee t where employee_id=1 将表中employee_id=1的记录利用value()实例化为一个对象,并将对象存储于e,value(t)的t是表的别名
使用对象的好处
Oracle的对象数据仍然以关系数据的形式存储。但对象的特性,如继承,封装等为开发人员提供了更加灵活的处理方式。同样,可以构造复杂的对象类型来封装复杂的多表查询。
此外使用对象传输数据比普通查询数据的传输效率更高
对象视图
如果应用程序已经开发完成,为了迎合对象类型而重建数据表是不现实的。对象视图正好可以解决。
创建对象视图
create or replace view ov_employee of employee with object oid(employee_id) as select employee_id a_id,employee_name,employee_position from employees
create or replace view ov_employee创建视图,of employee表示该视图基于对象类型employee;with object oid(employee_id)为对象视图指定了对象标识符,employee_id是对象类型employee中的属性employee_id,一旦指定了oid,那么,将利用Oracle内建数据类型REF来引用对象
可以利用value()获取记录到对象的映射
create or replace view vw_salary_employee as select s.salary_id,s.month,s.salary,value(o) e from salary s,employee o where s.employee_id=o.employee_id
value(o) e 用于获取employee实例,并指定别名 e
更新视图
insert into ov_employee values(employee(6,'张三','测试工程师'));
物化视图
与其他视图不同,物化视图是存储数据的。因此会占用相当大的存储空间
物化视图简介
物化视图的意义在于提高数据库性能,物化视图根据查询定义,将获得的结果存储到附属的数据表中。这样,当查询物化视图数据时,不再搜索数据表的数据,而是在物化视图的附属表中获取数据。对于大型数据表的汇总数据,这种策略尤其有效
创建及使用物化视图 ##
create materialized view 物化视图名称 as 视图定义
create materialized view mv_object_count as select object_type,count(*) from tmp_user_objects group by object_type
延迟载入
默认情况下,物化视图创建时,总是创建数据表,并将查询结果载入 数据表。但是这样太费资源了,此时可使用延迟载入。
创建物化视图时的延迟载入,使用build选项,该选项的默认值是immediate,表示立即载入,而创建物化视图的过程也包含数据加载的过程。指定延迟载入的build选项的值为deferred。语法如下:
create materialized view 视图名称 build deffered as 视图定义
删除物化视图
drop materialized view mv_object_count
create materialized view mv_object build deferred as select object_type, count(*) object_count from tmp_user_objects group by object_type
数据刷新
使用延迟加载策略,使数据不必立即加载,但物化视图中的数据必须与基础表的数据保持同步,这就涉及数据刷新的问题。
创建物化视图时,可通过refresh指定数据刷新策略,该选项的默认值是on demand,即需要用户手动刷新,从而完成数据同步。手动刷新时需要调用Oracle内置的存储过程
exec dbms_mview.refresh('mv_object_count');
exec用于执行一个存储过程; dbms_mview.refresh(‘mv_object_count’);用于刷新物化视图
除了手动刷新之外,Oracle提供另外一种刷新方式-当数据修改被提交时,自动同步数据。可以利用refresh on commit指定这种修改方式。
alter materialized view mv_object_count refresh on commit
alter materialized view mv_object_count用于修改物化视图的属性,refresh on commit用于将刷新策略修改为提交时同步数据。
这种策略存在着非常严重的弊端。物化视图的数据同步将耗费大量的数据库资源,因此当数据频繁更新时,将给数据库性能带来极大的负载。所以此策略仅适用于那些读取频繁,而更新较少的场景下。
当然,对于更新频繁的场景,应使用人工刷新的策略,即通过指定refresh on demand
查询重写
查询重写的对象为普通查询语句。查询重写是指查询时,Oracle改写查询语句,搜寻其他数据源,以保证相同结果的情况下提高执行效率。而这个新的数据源,往往是物化视图
启用查询重写功能:
alter materialized view mv_object_count enable query rewrite
alter materialized view mv_object_count修改视图属性,enable query rewrite用于启用查询重写
alter materialized view mv_object_count enable query rewrite
禁用查询重写
select count(*) from tmp_user_objects
这个语句虽然没有使用物化视图,但查询重写功能开始,自动将查询数据源指向了视图(视图的数据源就是这个表)