视图view,也称虚表,不占用物理空间,这个是相对概念,因为视图本身的定义语句还是要存在数据字典里。
视图只有逻辑定义,只是重新执行SQL。
视图是从一个或多个实际表中获得的,这些表的数据存放在数据库中。那些用于产生该视图的表叫做基表。一个视图也可以从另一个视图中产生。
视图的定义存在于数据库中,与此定义相关的数据并没有再存一份在数据库中。通过视图看到的数据存放在基表中。
视图看上去非常想数据库的物理表,对它的操作同任何其他的表一样。当通过视图修改数据时,实际上是在改变基表的数据;相反的,基表数据的改变也会自动反映在由基表产生的视图中。由于逻辑上的原因,有些视图可以修改对应的基表,有些则不能(仅仅能查询)。
- 物化视图(只存在于Oracle中)on commit和on demand
创建视图:在create view语句后加入子查询。
create [or replace] view v_emp[(alias[,alias]...)] as subquery [with read only];
例:create or replace view v$_emp_dept as select emp.deptno,emane,dname from emp join dept on emp.deptno = dept.deptno with read only;
在查询时,不需要再写完全的select查询语句,只需要简单的写上从视图中查询的语句就可以。
select * from v$_emp_dept;
--查找用户视图
select * from user_views where view_name = 'V_TEST01';
--修改视图里面的数据
insert into v_test01 (ename,empno,job,deptno) values('cai30',9921,'salesman',10);
--修改视图对应基表的数据
--修改数据:update view_name set...
若一个视图依赖于多个基本表,则一次修改视图只能修改一个基表数据。
删除数据:delete from view_name where....
同样,当视图依赖多个基表时,不能使用此语句来删除基表中的数据,只能删除依赖一个基表的数据。
insert into v_test01(ename,empno,job,deptno) values('cai30',9921.'salesman',10);
delete from v_test01 where ename='cai30';
update v_test01 set ename='cai10' where enmae = 'cai30';
删除视图:
drop view v_test01;
只读视图:
create or replace view v_test01 as select * from emp whit readonly;
测试插入:
insert into v_test01 (ename,empno,job,deptno) values('cai30',9921,'salesman',10);
授权视图:
使用system用户为scott增加权限:grant create view ,create table to scott;
使用system用户为Scott解锁:alter user scott acount unlock;
--视图使用:
求平均薪水的等级最低的部门名称:
select d.dname,d.deptno from dept d join(
select t.deptno,sg.grade gd from salgrade sg join(
select e.deptno,avg(e.sal) vsal from emp e group by e.deptno)t
on t.vsal between sg.losal and sg.hisal) t on t.deptno = d.deptno where t.gd = (
select min(t.gd) from (select t.deptno,sg.grade gd from salgrade sg)
join (select e.deptno,avg(e.sal) vsal from emp e group by e.deptno) t on t.vsal between sg.losal and sg.hisal)t);
查看sql语句发现有很多重复的sql子查询,克通过视图江重复语句抽象出来。
create view v_deptno_grade as select t.deptno,sg.grade gd from salagrade sg join (select e.deptno,avg(e.sal) vsal from emp e
group by e.deptno) t on t.vsal between sg.losal and sg.hisal;
使用视图替换
select d.dname,d.deptno from dept d join v_deptno_grade t on t.deptno = d.deptno where t.gd = (select min(t.gd) from v_deptno_grade t);