程序包开发相关概念及其应用

包用于将oracle相关的嵌套表、record、varray、记录、游标以及子程序逻辑组合在一起的一种方法。它由包规范(package specification)和包体(package body)两部分组成,其中保规范实际是包与其他应用程序之间的接口,它用于定义包的公用组件,包括常量、变量、游标、过程和函数等;包体中定义的组件只能在包内使用。
在user_source数据字典视图中可以查询得到包的定义和实现代码。
包的重载属性类似与高级语言中的相同定义,主要是为了实现功能相同,而传入参数不同的调用过程。
create or replace package pack_tsalary
is
 P_departid tsalary.departid% type ;
  -- 重载过程,根据传入参数更新对应记录的 salary
  procedure upd_salary(aemployeeid number ); 
  procedure upd_salary(adepartid varchar2 );
end ;
在包中定义了全局变量之后,有些情况下,会话中可能还需要初始化全局变量,此时可以使用包的构造过程,该过程没有任何名称,它位于程序尾部,并以begin end包括起来。在会话内第一次调用包的公用组件时,会自动执行其构造过程。
--select * from tsalary;
create or replace package body pack_tsalary
is
  procedure upd_salary(aemployeeid number )
  is
    myexception exception ;
  begin
    update tsalary set salary = 100 where employeeid = aemployeeid;
    if sql % notfound then
      raise myexception;
    end if ;
  exception
    when myexception then
      raise_application_error(- 20001 , ' 没发现员工 id ' ||aemployeeid|| ' 的员工 ' );
  end ;
  
  procedure upd_salary(adepartid varchar2 )
  is
  begin
    update tsalary set salary = 1001 where departid = adepartid;
    if sql % notfound then
      raise_application_error(- 20001 , ' 没发现部门 id ' ||adepartid|| ' 的员工 ' );
    end if ;
  end ;
  -- 构造函数,初始化全局变量
  begin
    p_departid := 'departid' ;
  end ;
包的公用函数既可以作为表达式的一部分使用,也可以在sql语句中使用。但如果要在sql语句中引用包的公用函数,那么该公用函数不能包含dml语句(insert/update/delete)也不能读写远程包的变量。例如有如下包定义:
create or replace package pack_tsalary
is
  function del_salary(aemployeeid varchar2 ) return number ;
end ;
create or replace package body pack_tsalary
is
  function del_salary(aemployeeid varchar2 )
  return number
  is
  begin
    delete from tsalary where employeeid = aemployeeid;
    return 1 ;
  end ;
那么基于表达式的调用方式可以成功:
if sys .pack_tsalary.del_salary( 'a' ) = 1 then
    dbms_output.put_line( ' 删除信息成功 ' );
  end if ;
而将包函数放在 sql 语句调用时则会提示 ora-14551: 无法执行查询中的 dml 语句。
  select sys .pack_tsalary.del_salary( '1' ) into aboolean from dual;
 dbms_output.put_line(aboolean);
为了避免这种调用错误的出现,我们可以使用 oracle 提供的纯度级别限制函数,对包的公用函数在定义时加以限制,定义纯度级别的语法为
pragma restrict_references(function_name,wnds[,wnps][,rnds][,rnps]);
其中 function_name 用于指定已经定义的函数名; wnds no write database )用于限制函数不能修改数据库数据(也就是禁止执行 dml 操作); wnps no write package )用于限制函数不能修改包变量; rnds no read database )用于限制函数不能读取数据库数据; rnps no read package )用于限制函数不能读取包变量。
create or replace package pack_tsalary
is
  function del_salary(aemployeeid varchar2 ) return number ;
  pragma restrict_references (del_salary, wnds );
end ;
这时如果在包体对应函数中出现 dml 语句,则编译时就出错,错误提示为“ PLS-00452: 子程序 ’del_salary’ 违反了它的相关编译指示”
create or replace package body pack_tsalary
is
  function del_salary(aemployeeid varchar2 )
  return number
  is
  begin
    delete from tsalary where employeeid = aemployeeid;
    return 1 ;
  end ;
end
 

你可能感兴趣的:(sql,exception,function,application,database,delete)