视图 view
命名的sql语句,存储在数据字典中
视图本身不包含数据(物化视图除外),视图的数据来源于基表或其他视图(创建视图时的查询所关联的表)
视图优缺点
可以限制数据的访问
方便管理
增加了数据的负担
查看视图的定义
user_views
视图分类
简单视图
只有单表
不包含去重,聚集,分组,函数,伪列,计算表达式
表中受非空约束的列在试图中没包含
可以在视图上执行DML操作,这叫可更新视图
对简单视图作delete和update的限制:
组函数
分组计算
有去重处理(distinct)
有rownum伪列
带有计算表达式所生成的伪列
对简单视图作insert的限制:
组函数
分组计算
有去重处理(distinct)
有rownum伪列
带有计算表达式所生成的伪列
表中受非空约束作用的列在视图中没有包含
复杂视图
包含一个或多个表
可以包含函数和分组数据
不能进行DML操作基表
创建语法
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name
[col1_alias,col2_alias...]
AS subquery
[WITH CHECK OPTION [CONSTRATINT constraint]]
[WITH READ ONLY [CONSTRATINT constraint]]
OR REPLACE : 如果视图存在则替换它(DDL重定义视图,生产中不要乱用)
[FORCE|NOFORCE]: 是否忽略基表不存在的错误 默认是不忽略(可以先建视图 再建表)
col1_alias,col2_alias...:可以自己定义列名 目的为了隐藏表中的原始列名
SUBQUERY: 是一个完整的SELECT语句,定义了视图的行和列
WITH CHECK OPTION: 用于控制DML视图时不满足视图的数据报错
WITH READ ONLY:设置只读视图
conn scott/seker
SQL> select 'drop table '||tname||' purge;' from tab where tname not in ('DEPT','EMP','BONUS','SALGRADE');
SQL> select deptno,max(sal) from emp group by deptno;
DEPTNO MAX(SAL)
---------- ----------
30
2850
20
3000
10
5000
SQL> create or replace view v1 as select deptno,max(sal) from emp group by deptno;
create or replace view v1 as select deptno,max(sal) from emp group by deptno
*
ERROR at line 1:
ORA-00998: must name this expression with a column alias
涉及到聚集函数时一定要取别名 别名的本质就是将非法的列名合法化
SQL> create or replace view v1 as select deptno,max(sal) sal from emp group by deptno;
View created.
SQL> select * from v1;
DEPTNO
SAL
---------- ----------
30
2850
20
3000
10
5000
SQL>
SQL> select VIEW_NAME,TEXT from user_views where VIEW_NAME='V1';
VIEW_NAME
------------------------------
TEXT
--------------------------------------------------------------------------------
V1
select deptno,max(sal) sal from emp group by deptno
SQL>
查询过程:在数据字典里找到视图的名字 根据名字取出视图的定义 执行定义的SQL 返回数据
删除视图
drop view view_name;
强制选项
SQL> create or replace force view v1 as select empno,ename,sal,deptno from my_emp where deptno=10;
Warning: View created with compilation errors.
SQL> select * from v1;
select * from v1
*
ERROR at line 1:
ORA-04063: view "SCOTT.V1" has errors
SQL> create table my_emp as select * from emp;
Table created.
SQL> select * from v1;
EMPNO ENAME
SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK
2450
10
7839 KING
5000
10
7934 MILLER
13001
10
SQL>
SQL> delete my_emp where empno=9999;
1 row deleted.
SQL> update v1 set sal=sal+1 where empno=7934;
1 row updated.
SQL> insert into v1 values(9999,'SEKER',1000,20);
1 row created.
SQL> select * from v1;
EMPNO ENAME
SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK
2450
10
7839 KING
5000
10
7934 MILLER
1302
10
SQL> 视图的条件是deptno=10 , 却可以插入deptno!=10的内容 没有约束不太合理
with check option 选项
对视图添加约束,只能操作符合定义中where条件的约束
SQL> create or replace force view v1 as select empno,ename,sal,deptno from my_emp where deptno=10 with check option;
View created.
SQL> insert into v1 values(8888,'BLUES',1000,20);
insert into v1 values(8888,'BLUES',1000,20)
*
ERROR at line 1:
ORA-01402: view WITH CHECK OPTION where-clause violation
SQL> insert into v1 values(8888,'BLUES',1000,10);
1 row created.
SQL>
带有with check option就依据当前定义的where子句生成check约束对象 这个约束对象默认系统取名 可以定义名字
SQL> create or replace force view v1 as select empno,ename,sal,deptno from my_emp where deptno=10;
View created.
SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name='V1';
no rows selected
SQL> create or replace force view v1 as select empno,ename,sal,deptno from my_emp where deptno=10 with check option ;
View created.
SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name='V1';
TABLE_NAME CONSTRAINT_NAME
C
---------- -------------------- -
V1
SYS_C005236
V
SQL> create or replace force view v1 as select empno,ename,sal,deptno from my_emp where deptno=10 with check option constraint ck_ON_V1;
View created.
SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name='V1';
TABLE_NAME CONSTRAINT_NAME
C
---------- -------------------- -
V1
CK_ON_V1
V
SQL>
WITH READ ONLY
视图是只读的,因此不能做DML操作
IN LINE 视图 (内嵌视图)
不需要创建
子查询出现在 from 子句中
查询那些人的工资大于所在部门的平均工资
SQL> select a.ename,a.sal,a.deptno,round(b.avgsal)
from emp a,
(select deptno,avg(sal) avgsal from emp group by deptno) b
where a.deptno=b.deptno and a.sal > b.avgsal order by 3;
ENAME
SAL
DEPTNO ROUND(B.AVGSAL)
---------- ---------- ---------- ---------------
KING
5000
10
2917
JONES
2975
20
2175
SCOTT
3000
20
2175
FORD
3000
20
2175
ALLEN
1600
30
1567
BLAKE
2850
30
1567
6 rows selected.
SQL>
(select deptno,avg(sal) avgsal from emp group by deptno) b 既是内嵌视图
内嵌视图+ROWNUM 实现分页
ROWNUM
伪列
随获取行的数量递增
SQL> select rownum,empno,sal from emp;
ROWNUM
EMPNO
SAL
---------- ---------- ----------
1
7369
800
2
7499
1600
3
7521
1250
4
7566
2975
5
7654
1250
6
7698
2850
7
7782
2450
8
7788
3000
9
7839
5000
10
7844
1500
11
7876
1100
12
7900
950
13
7902
3000
14
7934
1300
14 rows selected.
SQL>
SQL> select rownum,empno,sal from emp where rownum>=2;
no rows selected
SQL>
上面的执行语句类似于向下面的伪代码段传入表达式
rownum = 1
for i in (select * from emp)
loop
exit when not rownum>=N
OUTPUT record to temp
rownum = rownum+1
end loop
sort temp
试想一下 如果你传入的值时2 代码是否能运行
我们得到了 1>=2的条件 直接exit了 所以无获取行
rownum 使用在where时的规则
条件必须是从1开始
合法条件:小于(<) 一个大于1的数
小于等于(<=)一个大于等于1的数
不等于(<>) 一个非1和非0的正数
不符合上面条件 则没有返回行
rownum不能以任何表的名称作为前缀
这样才有意义 否则取不到行
练习:取出emp表按工资排序后结果的 6-10行
SQL> select * from (select rownum row_num,a.* from (select empno,ename,sal from emp order by sal) a) where row_num >=6 and row_num <=10;
---------- ---------- ---------- ----------
6
7934 MILLER
1300
7
7844 TURNER
1500
8
7499 ALLEN
1600
9
7782 CLARK
2450
10
7698 BLAKE
2850
SQL>
写SQL向替代变量传递值 第一个参数输入每页的行数 第二个参数输入要打印的第几页
分页算法
开始位置 大于 每页的行数*(要打印的第几页-1)
结束位置 小于等于 开始位置+每页的行数
select * from (select rownum rn,ename from emp) b where rn>&&r*(&&p-1) and rn <=&r*(&p-1)+&r;