分享

plsql 函数与过程的定义及应用

 redalx 2015-06-17

存储过程与函数

1
、存储过程 存储过程的参数 形式参数和实际参数,例如,有如下一个存储过程,该过程接收一个作家代码和一个工资值,将该作家的工资改为接收到的工资值。

代码

  1. create or replace procedure updateauths(
  2. p_authscode auths.author_code%type,
  3. p_authssalary auths.salary%type)
  4. as
  5. begin
  6. update auths set salary=p_authssalary where author_code=p_authscode;
  7. commit;
  8. end updateauths;

create or replace procedure updateauths(

p_authscode auths.author_code%type,

p_authssalary auths.salary%type)

as

begin

update auths set salary=p_authssalary where author_code=p_authscode;

commit;

end updateauths;

下面的PL/SQl块调用updateauths存储过程,将代码为A00011的作家的工资改为350元。

代码

  1. declare
  2. v_authorcode auths.author_code%type:='A00011';
  3. v_salary auths.salary%type:=350;
  4. begin
  5. updateauths(v_authorcode,v_salary);
  6. end;

declare

v_authorcode auths.author_code%type:='A00011';

v_salary auths.salary%type:=350;

begin

updateauths(v_authorcode,v_salary);

end;


v_authorcode
v_salary作为参数传递到存储过程updateauths中,这些参数是实际参数,简称实参。
p_authscode
p_authssalary就是形式参数,简称形参。 参数定义中,INOUTIN OUT代表参数的三种不同模式:
IN
:当调用存储过程时,该模式的形参接收对应实参的值,并且该是只读的,即不能被修改。默认为IN
OUT
:该形参被认为只能写,既只能为其赋值。在存储过程中不能读它的值。返回时,将该形参值传给相应的实参。 IN OUT:都允许。

代码

  1. create or replace procedure updateauthssalary(
  2. p_author_code in out auths.author_code%type,
  3. p_salary in number,
  4. p_name out auths.name%type) is
  5. v_salary_temp number; --定义存储过程中的局部变量
  6. begin
  7. select salary into v_salary_temp from auths where author_code=p_author_code;
  8. if v_salary_temp<300 then
  9. update auths set salary=p_salary where author_code=p_author_code;
  10. end if;
  11. select name into p_name from auths where author code=p_author_code;
  12. end updateauthssalary;

create or replace procedure updateauthssalary(

p_author_code in out auths.author_code%type,

p_salary in number,

p_name out auths.name%type) is

v_salary_temp number; --定义存储过程中的局部变量

begin

select salary into v_salary_temp from auths where author_code=p_author_code;

if v_salary_temp<300 then

update auths set salary=p_salary where author_code=p_author_code;

end if;

select name into p_name from auths where author code=p_author_code;

end updateauthssalary;

(1)参数的数据类型 在定义一个存储过程参数时,不能指定CHAR类型和VARCHAR2类型形参的长度,也不能指定NUMBER形参的精度和标度。这些约束由实参来传递。 例如,下面的存储过程定义不合法,将产生一个编译错误:

代码

  1. create or replace procedure proc_auths(
  2. --参数定义了类型长度,将产生编译错误。
  3. p_code in out varchar2(6),
  4. p_salary out number(8,2)) as
  5. begin
  6. select salary into p_salary from auths where author_code=p_code;
  7. end proc_auths;

create or replace procedure proc_auths(

--参数定义了类型长度,将产生编译错误。

p_code in out varchar2(6),

p_salary out number(8,2)) as

begin

select salary into p_salary from auths where author_code=p_code;

end proc_auths;

修改上面存储过程的定义为:

代码

  1. create or replace procedure proc_auths(
  2. --参数定义了类型长度,将产生编译错误。
  3. p_code in out varchar2,
  4. p_salary out number) as
  5. begin
  6. select salary into p_salary from auths where author_code=p_code;
  7. end proc_auths;

create or replace procedure proc_auths(

--参数定义了类型长度,将产生编译错误。

p_code in out varchar2,

p_salary out number) as

begin

select salary into p_salary from auths where author_code=p_code;

end proc_auths;


p_code
的长度约束和p_salary的精度,标度约束由实参传递。

代码

  1. delcare
  2. v_code varchar2(6);
  3. v_salary number(8,2);
  4. begin
  5. v_code:='A00001';
  6. proc_auths(v_code,v_salary);
  7. end;

delcare

v_code varchar2(6);

v_salary number(8,2);

begin

v_code:='A00001';

proc_auths(v_code,v_salary);

end;

注意,如果使用%type为参数定义类型,那么该参数具有定义在形参上而不是通过实参传递的数据长度。

代码

  1. create or replace procedure query_salary(
  2. p_code in out auths.author_code%type,
  3. p_salary out auths.salary%type) as

create or replace procedure query_salary(

p_code in out auths.author_code%type,

p_salary out auths.salary%type) as

--那么由于author_code的长度为6,因此p_code的长度也为6 (2)参数的传值方式 位置表示法、名称表示法 如有这样的存储过程

代码

  1. create or replace procedure insert_auths(
  2. p_code auths.author_code%type,
  3. p_name auths.name%type,
  4. p_sex auths.sex%type,
  5. p_birthdate auths.birthdate%type) as

create or replace procedure insert_auths(

p_code auths.author_code%type,

p_name auths.name%type,

p_sex auths.sex%type,

p_birthdate auths.birthdate%type) as

下面进行两种方法的调用:

代码

  1. declare
  2. v_code varchar2(6);
  3. v_name varchar2(12);
  4. v_sex number(1);
  5. v_birthdate date;
  6. begin
  7. v_code:='A00021';
  8. v_name:='';
  9. v_sex:=1;
  10. v_birthdate:='5-seq-70';
  11. --实参的位置顺序与形参的位置顺序相对应。---位置表示法
  12. insert_auths(v_code,v_name,v_sex,v_birthdate);
  13. --实参名与形参名对应,这样就可以重新排列参数的先后顺序。---命名表示法
  14. end;

declare

v_code varchar2(6);

v_name varchar2(12);

v_sex number(1);

v_birthdate date;

begin

v_code:='A00021';

v_name:='';

v_sex:=1;

v_birthdate:='5-seq-70';

--实参的位置顺序与形参的位置顺序相对应。---位置表示法

insert_auths(v_code,v_name,v_sex,v_birthdate);

--实参名与形参名对应,这样就可以重新排列参数的先后顺序。---命名表示法

end;

注意,位置表示法和命名表示法在一些调用中也可以混合使用。但是,如果出现第一个用命名表示法的参数时,后面的参数也必须使用命名表示法传值。 (3)参数的缺省值 如可以这样:
p_entry_date_time auths.entry_date_time%type:sysdate,
p_sex auths.sex%type default 1



2
、创建函数 函数与存储过程非常类似,都有三种模式的参数。
它们都可以存储在数据库中(当然过程与函数也可以不在于数据库中),并且在块中调用。 与存储过程不同,存储过程只能作为一个PL/SQL语句调用,而函数作为表达式的一部分调用。并且它们的定义、可执行、异常处理部分是不同的。 例如,如作家表中男作家或女作家的工资在200元以上的人数大于百分之七十,则下面的函数返回TRUE,否则返回FALSE

代码

  1. create or replace function salarystat(
  2. p_sex auths.sex%type)
  3. return boolean is
  4. v_currentsexauthors number;
  5. v_maxauthors number;
  6. v_returnvalue boolean;
  7. v_percent constant number:=70;
  8. begin
  9. --获得满足条件的作家的最大数。
  10. select count(author_code) into v_maxauthors from auths where sex=p_sex and salary>=200;
  11. select count(author_code) into v_currentsexauthors from auths where sex=p_sex;
  12. if(v_maxauthors/v_currentsexauthors*100)>v_percent then
  13. v_returnvalue:=true;
  14. else
  15. v_returnvalue:=false;
  16. end if;
  17. return v_returnvalue;
  18. end salarystat;

create or replace function salarystat(

p_sex auths.sex%type)

return boolean is

v_currentsexauthors number;

v_maxauthors number;

v_returnvalue boolean;

v_percent constant number:=70;

begin

--获得满足条件的作家的最大数。

select count(author_code) into v_maxauthors from auths where sex=p_sex and salary>=200;

select count(author_code) into v_currentsexauthors from auths where sex=p_sex;

if(v_maxauthors/v_currentsexauthors*100)>v_percent then

v_returnvalue:=true;

else

v_returnvalue:=false;

end if;

return v_returnvalue;

end salarystat;

下面进行调用:

代码

  1. declare
  2. cursor c_auths is
  3. select distinct sex from auths;
  4. begin
  5. for v_authsrecord in c_auths loop
  6. if salarystat(v_authsrecord.sex) then
  7. update auths set salary=salary-50 where sex=v_authsrecord.sex;
  8. end if;
  9. end loop;
  10. end;

declare

cursor c_auths is

select distinct sex from auths;

begin

for v_authsrecord in c_auths loop

if salarystat(v_authsrecord.sex) then

update auths set salary=salary-50 where sex=v_authsrecord.sex;

end if;

end loop;

end;


return
也可以用在存储过程中。在这种情况下,它没有参数。当执行了不带参数的return语句后,立刻将控制返回到调用环境,并将OUTIN OUT模式的形参的当前值传给实参,然后继续执行调用存储过程后的语句。 在使用函数与存储过程时,一般情况下,如果只有一个返回值,则使用函数;如果有多个返回值则使用存储过程。尽管函数的参数可以是OUT模式,但是一般不这样使用。 3、删除过程与函数
drop procedure procedurename;
drop function functionname;

4
、库存子程序和局部子程序 前面的子程序都是存储在数据库中的子程序,即库存子程序。
这些子程序是由ORACLE命令创建的,并可在其它的PL/SQL块中调用。它们在创建时要进行编译,并将编译后的代码存储在数据库中。当子程序被调用时,编译后的代码从数据库中读出并执行。 一个子程序也可以在块的定义部分创建,这样的子程序被叫作局部子程序。 下面定义了一个局部函数formatname

代码

  1. declare
  2. cursor c_allauthors is
  3. select name,sex from auths;
  4. v_formattedname varchar2(60);
  5. function formatname(p_name in varchar2,p_sex in number)
  6. return varchar2 is
  7. v_sex varchar2(16);
  8. begin
  9. if p_sex=1 then
  10. v_sex:='';
  11. else
  12. v_sex:='';
  13. end if;
  14. return p_name||'('||v_sex||')';
  15. end formatname;
  16. begin
  17. for v_authsrecord in c_allauthors loop
  18. v_formattedname:=
  19. formatname(v_authsrecord.name,v_authsrecord.sex);
  20. dbms_output.put_line(v_formattedname);
  21. end loop;
  22. end;

declare

cursor c_allauthors is

select name,sex from auths;

v_formattedname varchar2(60);

function formatname(p_name in varchar2,p_sex in number)

return varchar2 is

v_sex varchar2(16);

begin

if p_sex=1 then

v_sex:='';

else

v_sex:='';

end if;

return p_name||'('||v_sex||')';

end formatname;

begin

for v_authsrecord in c_allauthors loop

v_formattedname:=

formatname(v_authsrecord.name,v_authsrecord.sex);

dbms_output.put_line(v_formattedname);

end loop;

end;

如上例,在无名块的定义部分创建了formatname函数。这个函数只在创建它的块中可用,它的作用域从创建它开始到结束。 局部子程序只能在定义部分的最后被创建,如果将formatname函数移到上面,将会出现编译错误。子程序必须先定义再引用。

[@more@]

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多