存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。
存储过程到底是干嘛用的?简单讲就是存放一些写好的执行语句,创建完后存在数据库中,可反复调用,不用每次再写一遍,类比Java中的函数,存储过程还可以有入参、有返回,存储过程中的内容根据传入的参数不同执行结果也不同,一次编译永久执行。
第一个存储过程Hello World
create or replace procedure mypro is
begin
dbms_output.put_line('hello world!');
end;
在plsql中运行完上面语句,不代表编译通过,右键点击存储过程名,选择“编辑”,再点击运行按钮,可以看到底部是否编译成功。
无参:
create or replace procedure mypro is
begin
dbms_output.put_line('hello world!');
end;
有参:
create or replace procedure mypro(param1 in varchar,param2 out varchar, param3 in out varchar) is
define1 number;
begin
dbms_output.put_line('hello world!');
end;
其中参数in表示输入参数,不写默认为in
out表示返回值参数,类型可以使用任意Oracle中的合法类型。
out模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调用他的过程
in out表示该参数可以向该过程中传递值,也可以将某个值传出去。
drop procedure mypro();
【执行 方式一 SQL或命令窗口】
无参
begin
mypro();
end;
有参
declare
a varchar(32);
b varchar(32);
c varchar(32);
begin
a:='xxx';
b:='xxx';
c:='xxx';
mypro(a,b,c);
end;
【执行 方式二 命令窗口下】
--无返回调用
exec mypro('xx','xx');
有返回调用
SQL>var rs varchar
SQL>exec mypro('xx',:rs);
或者 call mypro('xx',:rs);
前面写了那么多没有真枪实弹,都是白学。【案例1:备份数据,再更新。返回备份后的记录数。】
create table test1(id number(10),
name varchar2(32)
);
create table test2(id number(10),
name varchar2(32)
);
insert into test1(id,name) values(1,'初始数据');
//备份数据,再更新。返回备份后的记录数。
create or replace procedure mypro(in_id in number,rs out number) is
vsql varchar(80);
begin
vsql:='insert into test2 select * from test1 where id='||in_id;
execute immediate vsql;
update test1 set name='更新' where id=1;
commit;
select count(*) into rs from test2 ;
end;
执行
SQL>var rs number
SQL> exec mypro(1,:rs);
执行结果:
PL/SQL procedure successfully completed
rs
---------
1
要点
游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。
游标有两种类型:显式游标和隐式游标。SELECT...INTO...查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标。但是如果要提取多行数据,就用到显式游标,显式游标对应一个返回结果为多行多列的SELECT语句。
游标的形式有多种
1. for .. in .. loop形式
...
is
v_rs varchar2(400);
cursor cur is select name from test1;
begin
v_rs:='';
for c in cur loop
v_rs:=v_rs||c.name||',';
end loop;
...
2.普通形式open cursor
...
is
val varchar2(100);
v_rs varchar2(400);
cursor cur is select name from test1;
begin
v_rs:='';
open cur;
loop
fetch cur into val;
exit when cur%notfound;
v_rs:=v_rs||val||',';
end loop;
close cur;
...
传闻还有种更高明的写法,水平有限,感兴趣的可以深入研究一下。
但还有一种在函数中的写法 open cur for vsql
动态SQL
create or replace function func_test(
i_sql varchar2
)
return varchar2
is
val varchar2(100);
v_rs varchar2(400);
TYPE i_cursor_type IS REF CURSOR;
cur i_cursor_type;
begin
v_rs:='';
open cur for i_sql;
loop
fetch cur into val;
exit when cur%notfound;
v_rs:=v_rs||val||',';
end loop;
close cur;
return substr(v_rs,0,length(v_rs)-1);
end func_test;
要点
触发器是在事件发生时隐式地自动运行的PL/SQL程序块,不能接收参数,不能被调用。是一种特殊的存储过程。
触发器的创建
--有数据插入时触发事件,运行begin..end;中的语句块。
create or replace trigger test_tri
after insert on test1
for each row
begin
insert into test1(id) values(1666);
end;
案例——阻止删除
create or replace trigger my_test
before delete on test1
for each row
begin
if :old.name like '%数据%' then
raise_application_error(-20001, '请不要删除这些数据');
end if;
end;
笔记
认识两种循环:
for循环
declare
i number;
begin
for i in 1 .. 100 loop
dbms_output.put_line(i);
end loop;
end;
while循环(for循环忘记怎么写,就用while)
declare
i number;
begin
i:=1;
while i<101 loop
dbms_output.put_line(i);
i:=i+1;
end loop;
end;