以前我们写的PL/SQL语句程序多是瞬时的,没命名的;
现在我们把命名的PL/SQL块叫做子程序;
子程序
结构没什么区别:声明,执行,异常;但声明也是必须的;
优点:模块化;可重用性;可维护性;
类型:1,过程,用于执行某项操作;
2,函数,用于执行某项操作并返回值;
过程
使用create procedure语句创建
语法:create or replace procedure <proc_name>
[parameter list]
Is|as
<local declarations>;
Begin
(executable statements)
End;
这里的is|as就相当于declare;
除了拥有前面的一个过程声明语句外,其他和以前的PL/SQL一样;
参数模式:
In 接受值,默认值;
Out 将值返回给子程序的调用程序
In out 接受值并返回已更新的值
参数的书写格式:[(参数1 in|out|in out 参数类型, 参数2 in|out|in out 参数类型,…)]
创建不带参数过程的例子:
create or replace procedure xiaojiujiu
as
i integer;
j integer;
begin
dbms_output.put_line('print xiaojiujiu');
for i in 1..9 loop
for j in 1..9 loop
if i>=j then
dbms_output.put(to_char(j)||'*'||
to_char(i)||'='||to_char(i*j)||' ');
end if;
end loop;
dbms_output.put_line('');
end loop;
end;
/
创建的过程就象你创建的表一样,属于当前操作的用户,其他连接的用户将可以通过 用户名.过程名 来调用过程;数据字典是user_source; drop同样可以象删除表一样删除存储过程
注意,创建过程的时候并不会执行过程,必须在这之后调用过程来执行;
调用的方法:
1, execute procedure_name(list of parameters) 比如execute items(‘i201’);
2, 可以在匿名块中调用;比如begin items(‘i201’) end;
创建带参数过程的例子:
create or replace procedure queryEmpName(sFindNo emp.EmpNo%type)
as
sName emp.ename%type;
sJob emp.job%type;
begin
select ename,job into sName,sJob from emp
where empno=sFindNo;
dbms_output.put_line('ID is '||sFindNo||' de zhigong name is '||
sName||' gongzuo is '||sJob);
exception
when no_data_found then
dbms_output.put_line('no data');
when too_many_rows then
dbms_output.put_line('too many data');
when others then
dbms_output.put_line('error');
end;
/
所以,我们发现带参数的过程真正实现了运行的交互性;
函数
Create or replace function <fuction-name>
[parameters list]
Return datatype
is|as
…….
注意函数和过程的输入参数以及函数的返回参数的定义都不能定义精度;默认的参数模式是输入;
其实和过程完全一样;只是函数一般不会用输出参数,因为他本身就会返回数据嘛,何必慢慢地用参数返回数据呢;
例子:
create or replace function getName(sno varchar2)
return varchar
is
name varchar(12);
begin
select ename into name from emp
where empno=sno;
return name;
exception
when too_many_rows then
dbms_output.put_line('too many data');
when others then
dbms_output.put_line('error');
end;
/
调用的时候必须接受返回值:
declare
name varchar(12);
begin
name:=getname('7902');
dbms_output.put_line(name);
end;
/
或者
select getname(7369) from dual
或者
Select * from emp where ename=getname(‘7369’);
过程和函数的区别
过程作为PL/SQL语句块来执行;
函数作为表达式的一部分调用;
在规则说明中不包含return;
必须包含return;
可以返回任何值;
必须返回单个值;
可以包含return语句,但是与函数不同,不能返回值;必须包含至少一条return;
出现编译错误的时候可以show errors或者desc user_errors来调试;
创建:
调用:
我们发现必须使得输入参数和定义的顺序一致,但是也不一定要这样,可以用符号=>来乱序传入参数;
但是注意,是过程定义的参数=>调用块的值或参数而不是相反,Oracle 太不懂语言了;
自主事务:pragma autonomous_transaction;
第一个事务:
create or replace procedure p1
as
[pragma autonomous_transaction]
begin
insert into student values(105,'luweiyu','男');
rollback;
end;
/
第二个事务调用了第一个事务:
create or replace procedure p2
as
begin
update student set se='女';
p1;
end;
/
但是我们看到的是,p1中执行rollback的时候把p2中的update操作也给回滚从而结束了事务;
所以:事务是互相影响的;如果我们不希望发生这样的情况,我们引进了自主事务的做法:
在as和begin中间加入pragma autonomous_transaction;语句用于表示p1的事务是自主结束的,它将不会影响调用它的p2的事务的结束等;
程序包
程序包是模块化的数据类型,游标,子程序,变量等数据对象的集合;
包括两个部分:
1, 说明部分,可以只说明,类似接口;
a) 使用create package进行创建
b) 包含公用对象和类型
c) 声明类型,变量,常量,异常,游标和子程序
d) 可以在没有程序包主体的情况下存在
2, 主体,可以没有实现的主体部分;
a) 使用create package body
b) 包含子程序和游标的定义
c) &nbs