Oracle之对象

视图

视图封装了复杂查询语句,可以看做是表的部分内容映射

视图的存在可以直观感受数据的关系,并且对一些敏感源数据进行隐藏。

虽然视图是原始表的内容映射,但是不建议直接对视图进行DML操作

创建一张视图:

create or replace view Name(自定义字段名) //or replace 保证创建同名视图会自动删除原视图
as
select ...
[with check opinion] //允许在不影响视图根本规则的情况下适当修改数据
[with read only]  //只读,不允许修改

查询视图与查询一般表没什么区别

select ... from viewName;

索引

可以快速定位并减少磁盘IO,与物理表独立存在,需要定期维护

唯一性索引 非唯一索引

定义约束 或 create index

原则:维护索引列的唯一性+快速访问;查询量大的表;where查询频繁的字段;非重复数据占比大的字段(如pk字段);复合索引的主列应是使用频繁的字段;数据量多的表(大于5M)

查询结果行占比5%以下,用索引最好

多列查询的话,复合索引优于单列索引,因为只需查询索引块

调优:索引与表不要放在同一个表空间,否则容易产生IO冲突;而且不放在同一块硬盘,还可以增加并行度

tip

一个查询可以同时用到多个索引,先访问一个索引得到结果1,此基础*问第二个索引,且效率是高于全表扫描的,但是低于复合索引

sql优化的实质就是在结果正确的前提下。用优化器认识的语句充分使用索引。尽量访问最少的数据块,减少磁盘IO,节省资源

in 不能使用索引

!= 不能使用索引

like 'xxx' 匹配模式不能通配符开头,这样就不能使用索引

索引列不要参与计算和函数,包括隐式类型转换

>=优于>,因为等于可以先定位

sga共享池

表连接条件放在最前,过滤大的条件放在最后

packages,首次调用将整个包导入内存

cached sequences 生成序列

varchar 替代 char

序列

创建序列

create sequence Name
[
start with num
increment by step
order
cache num			//预先存取一些序列值,保证存取速度快,但是如果数据库挂掉,序列就会紊乱,所以一般用nocache
nocycle  			//nocycle保证序列用于不同表时id唯一
]

//不缓存,序列值按3循环
create sequence a
start with 1
increment by 1
cycle 3
nocache;

alter sequence Name increment by num;//修改step

取值

select name.nextval,name.currval from dual;//先有nextval,才能用currval

同义词

其实就是dual,是sys用户下的一张表,可以看做是杂货堆

PLSQL块

类似编程的代码块,有特定的格式,可以批量执行一些固定操作

declare
	var type;
begin
	//content
	...
	exception
		when e then
		...
end

set serveroutput on //设置输出显示
声明变量

var type;

类型可以直接写:eno number;

也可以直接映射某表的字段类型:eno emp.empno%type;

变量也可以是整条记录(类似Javabean),但是类型就要映射了:dept dept%rowtype;

语法

en:=&no // 获取输入

Loop循环
// do while
loop
	...
	exit when xxx;
	...
end loop;

// while
while(...) loop
	...
end loop;

//for1
for xx in xxxx loop
	...
end loop;
//for2
for xx..xxxx loop
	...
end loop;
if选择
if 条件 then
	...
end if

if 条件 then
	...
else
	...
end if

if 条件 then
	...
elif 条件 then
	...
else
	...
end if
goto跳转

Oracle之对象

游标

通过PLSQL创建,主要对查询语句结果进行遍历,类似于java集合的迭代器。

存在于内存中,并非数据库对象

声明——>打开——>遍历——>关闭

declare
	cursor Name is select ...;
	//一般游标一定伴随一个记录对象
	xxx table%rowtype;
	length number;
begin
	length:=Name%rowcount;//取游标长度
	for xxx in Name loop
		...
	end loop;
end;

//使用fetch抓取游标
declare
	...
begin
	open Name;//先要开启游标
	fetch Name into xxx;//从游标取值
	while(Nmme%found) loop//查看游标是否取完不存在?
		....
		fetch Name into xxx;//循环取值
	end loop
end

//loop方式取值
declare
	...
begin
	open Name;
	loop
		fetch Name into xxx;
		exit when Name%notfound;
		...
	end loop
end

//注:在打开游标前最好先判断游标是否已经打开
if Name%isopen then
	null;
else
	open Name;
end if;
//以上游标属于静态游标,声明即确定内容;也可以设定动态游标
declare
	TYPE typename is ref cursor [return xxx%xxx];//自定义一个游标变量类型,允许指定游标内容类型
    var typename;//声明游标变量
    xxx xxx%xxx;//声明记录变量
    str varchar(200);//建立一个语句变量
begin
	...
end

//example
declare
	TYPE stus_cursor is ref cursor return student%rowtype;
	stus stu_cursor;
	stu student%rowtype;
	str varcaar(200);
begin
	str:='select * from student where sid between :x and :y';
	open stus for str using 20,23;
	或者
	open stus for select * from student where sid between 20 and 23;
	
	fetch stus into stu;
	while(stus%found) loop
		fetch stus into stu;
		...
	end loop
end

//动态游标如果不想自定义也可以使用系统游标
declare
	stus sys_refcursor;//自定义类型建立变量一步到位
	...
begin
	...
end

(自定义)函数

数据库的函数是一个有返回值的过程

其格式也是类似PLSQL

create or replace function funName([param xxx.xxx%xxx])  //参数定义一如前面PLSQL声明变量一致
return type as var type
begin
	...
end

//example:根据雇员的编号查询出雇员的年薪
CREATE OR REPLACE FUNCTION myfun(eno emp.empno%TYPE) 
RETURN NUMBER AS rsal NUMBER ;    //这不是特指定义返回值变量,普通变量也可以的,只要最后返回的变量在这里定义即可
BEGIN
SELECT (sal+nvl(comm,0))*12 INTO rsal FROM emp WHERE empno=eno ;
RETURN rsal ;                     //返回值一定要在前面定义过
END ;

?返回多个变量

自定义函数的调用与系统函数一致,直接调用即可

前面提到游标对象可以迭代获取一组数据的记录

这里可以将游标与函数结合,由函数接收参数,由动态游标取值,甚至直接返回一个游标(return sys_refcursor as Name sys_refcursor)

存储过程

存储过程相当于是函数的反面,功能相似,只是存储过程没有返回值,而函数要有返回值

语法也及其相似

create or replace procedure Name([param xxx%xxx])
as
	//声明变量
begin
	...
end

param参数有三种类型:in,out,in out
in 就是简简单单的输入参数

关键就是这个out,前面说过存储过程和函数的区别就在于存储过程没有返回值;但是参数加上out ,其实就是隐式的返回值

out 参数就是外界传入一个“返回值地址”变量,由存储过程操作并将结果传入该地址,外界调用存储过程后该变量结果事实上已经产生变化;

in out 参数就是参数既当传入值,有作为返回值。只是结果存储过程一顿操作,原始值被修改。

//example1
Create or replace procedure proc_is_exist(na emp.ename%type,is_exist out number)
as
   name varchar(22);
begin
   select count(*) into is_exist from emp where ename = na;
end;
declare
   i number;
begin
   proc_is_exist('sdsdsd',i);
   dbms_output.put_line(i);     //外界将参数i传入过程,等待过程操作得到结果赋值。最后i结果为count(*)
end;

//example2
CREATE OR REPLACE PROCEDURE myproc(dno IN OUT dept.deptno%TYPE,name dept.dname%TYPE,dl dept.loc%TYPE)
AS
cou NUMBER ;
BEGIN
    SELECT COUNT(deptno) INTO cou FROM dept WHERE deptno=dno ;
    IF cou=0 THEN
        INSERT INTO dept(deptno,dname,loc) VALUES(dno,name,dl) ;
        DBMS_OUTPUT.put_line('部门插入成功!') ;
        dno := 1 ;
    ELSE
        DBMS_OUTPUT.put_line('部门已存在,无法插入!') ;
        dno := -1 ;
    END IF ;
END ;

DECLARE
	deptno dept.deptno%TYPE ;
BEGIN 
    deptno := 12 ;
    myproc(deptno,'开发','南京') ;
    DBMS_OUTPUT.put_line(deptno) ;  //首先以传入的deptno查看结果,根据查看结果将1、-1覆盖原变量作为返回值,外界接收的deptno值只能是1,-1
END ;
//删除存储过程
drop procedure Name; 

触发器

create or replace triggle Name
before/after
insert/delete/update on tableName //注:触发器的执行代码中不允许提交关于查询基表的语句?
[for each row]  //加for each row 是行级触发器,针对每行记录动作触发响应
[when(条件)]  //限制触发器,当满足条件触发器启用
declare
	...
begin
	...
end

触发器可以实现日志记录和数据备份

上一篇:RF关键字使用


下一篇:oracle的for语句