`

精通Oracle10编程SQL(12)开发包

阅读更多
/*
 *开发包
 *包用于逻辑组合相关的PL/SQL类型(例如TABLE类型和RECORD类型)、PL/SQL项(例如游标和游标变量)和PL/SQL子程序(例如过程和函数)
 */
--包用于逻辑组合相关的PL/SQL类型、项和子程序,它由包规范和包体两部分组成
--建立包规范:包规范实际是包与应用程序之间的接口,它用于定义包的公用组件,包括常量、变量、游标、过程和函数等
--在包规范中所定义的公用组件不仅可以在包内引用,而且也可以由其他的子程序引用
--示例
CREATE OR REPLACE PACKAGE emp_package IS
  g_deptno number(3):=30;
  procedure add_employee(eno number,name varchar2,salary number,dno number default g_deptno);
  procedure fire_employee(eno number);
  function get_sal(eno number) return number;
END emp_package;

--建立包体
--应用程序只能直接调用该包内的所有公用组件,而私有函数VALIDATE_DEPTNO则不能被应用程序调用
CREATE OR REPLACE PACKAGE BODY emp_package 
IS
  FUNCTION validate_deptno(v_deptno number)
     return boolean
  is
     v_temp int;
  begin
     select 1 into v_temp from dept where deptno=v_deptno;
     return true;
  exception
     when NO_DATA_FOUND THEN
        RETURN FALSE;
  end;
  
  PROCEDURE add_employee(eno number,name varchar2,salary number,dno number default g_deptno)
  is
  begin
       if validate_deptno(dno) then
         insert into emp(empno,ename,sal,deptno) values(eno,name,salary,dno);
       else
         raise_application_error(-20010,'不存在该部门');
       end if;
  exception
       when DUP_VAL_ON_INDEX THEN
          raise_application_error(-20011,'该雇员已存在');
  end;
  
  PROCEDURE fire_employee(eno number)
  is
  begin
     delete from emp where empno=eno;
     if SQL%NOTFOUND then
        raise_application_error(-20012,'该雇员不存在');
     end if;
  end;
  
  FUNCTION get_sal(eno number) return number
  is
    v_sal emp.sal%TYPE;
  begin
    select sal into v_sal from emp where empno=eno;
    return v_sal;
  exception
    when NO_DATA_FOUND THEN
       raise_application_error(-20012,'该雇员不存在');
  end;
end emp_package;

--调用包组件
--注意,当在其他应用程序中调用包的组件时,必须要加包名作为前缀(包名.组件名)
--示例一:在同一个包内调用包组件,如上如示
  PROCEDURE add_employee(eno number,name varchar2,salary number,dno number default g_deptno)
  is
  begin
       if validate_deptno(dno) then
         insert into emp(empno,ename,sal,deptno) values(eno,name,salary,dno);
       else
         raise_application_error(-20010,'不存在该部门');
       end if;
  exception
       when DUP_VAL_ON_INDEX THEN
          raise_application_error(-20011,'该雇员已存在');
  end;

--示例二:调用包公用变量
--在SQL*Plus中调用包公用变量
--当在其他应用程序中调用包的公用变量时,必须要在公用变量名前加包名作为前缀,并且注意其数值在当前会话内一直生效
exec emp_package.g_deptno:=20

--示例三:调用包公用过程
--在SQL*Plus中调用包公用过程
exec emp_package.add_employee(1111,'MARY',2000)

select * from dept;
select * from emp;

--示例四:调用包公用函数
var salary number
exec :salary:=emp_package.get_sal(7788)
print salary

--示例五:以其他用户身份调用包公用组件
--当以其他用户身份调用包的公用组件时,必须在组件名前加用户名和包名作为前缀(用户名.包名.组件名)
exec haiya1.emp_package.add_employee(1155,'SCOTT',1200)

--调用远程数据库包的公用组件
--当调用远程数据库包的公用组件时,在组件名之前加包名作为前缀,在组件名之后需要带有数据库链名作为后缀(包名.组件名@数据库存链名)
exec emp_package.add_employee@orasrv(1116,'SCOTT',1200)

--查看包源代码
select text from user_source where name='EMP_PACKAGE' AND type='PACKAGE';

--删除包
--如果只删除包体,那么可以使用命令DROP PACKAGE BODY;如果同时删除包规范和包体,那么可以使用命令DROP PACKAGE
DROP PACKAGE emp_package;

--使用包重载
--重载是指多个具有相同名称的子程序
--下面以建立使用雇员号和雇员名取得雇员工资、解雇雇员的包规范为例,说明定义重载过程和重载函数的方法
--建立包规范
CREATE OR REPLACE PACKAGE overload IS
   FUNCTION get_sal(eno number) return number;
   FUNCTION get_sal(name varchar2) return number;
   PROCEDURE fire_employee(eno number);
   PROCEDURE fire_employee(name varchar2);
END;

--建立包体
CREATE OR REPLACE PACKAGE BODY overload IS 
   FUNCTION get_sal(eno NUMBER) RETURN NUMBER
   IS 
      v_sal emp.sal%TYPE;
   BEGIN
      select sal into v_sal from emp where empno=eno;
      return v_sal;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         raise_application_error(-20020,'该雇员不存在');
   END;
   
   FUNCTION get_sal(name varchar2) return number
   is
      v_sal emp.sal%TYPE;
   BEGIN
      SELECT sal into v_sal from emp where upper(ename)=upper(name);
      return v_sal;
   EXCEPTION
      WHEN NO_DATA_FOUND THEN
         raise_application_error(-20020,'该雇员不存在');
   END;
   
   PROCEDURE fire_employee(eno number) IS 
   BEGIN
      DELETE FROM emp where empno=eno;
      if SQL%NOTFOUND then
         raise_application_error(-20020,'该雇员不存在');
      end if;
   END;
   
   PROCEDURE fire_employee(name varchar2) IS
   BEGIN
      DELETE FROM emp where upper(ename)=upper(name);
      if SQL%NOTFOUND THEN
         raise_application_error(-20020,'该雇员不存在');
      end if;
   END;
END;

--调用重载过程和重载函数
--在调用重载过程和重载函数时,PL/SQL执行器会自动根据输入参数值的数据类型确定要调用的过程和函数
var sal1 number
var sal2 number
exec :sal1:=overload.get_sal('scott')
exec :sal2:=overload.get_sal(7788)
print sal1 sal2


--使用包构造过程
--在包中定义了全局变量之后,有些情况下,会话中可能还需要初始化全局变量,此时可以使用包的构造过程
--下面以限制老员工工资不能低于雇员的最低工资,并且不能超过雇员的最高工资为例,说明使用包构造过程的方法
--建立包规范
CREATE OR REPLACE PACKAGE emp_package IS
  minsal NUMBER(6,2);
  maxsal number(6,2);
  procedure add_employee(eno number,name varchar2,salary number,dno number);
  procedure upd_sal(eno number,salary number);
  procedure upd_sal(name varchar2,salary number);
END;

--建立包体
--为了运行包组件时将雇员的最低工资和最高工资分别赋值给全局变量minsal和maxsal,需要在包体内编写构造过程。
--包的构造过程没有任何名称,它是在实现了包的其他过程之后,以BEGIN开始,以END结束的部分。
CREATE OR REPLACE PACKAGE BODY emp_package IS
  procedure add_employee(eno number,name varchar2,salary number,dno number)
  is
  begin
    if salary between minsal and maxsal then
       insert into emp(empno,ename,sal,deptno) values(eno,name,salary,dno);
    else
       raise_application_error(-20001,'工资不在范围内');
    end if;
  exception
    when dup_val_on_index then
       raise_application_error(-20002,'该雇员已经存在');
  end;
  
  procedure upd_sal(eno number,salary number) is 
  begin
    if salary between minsal and maxsal then
       update emp set sal=salary where empno=eno;
       if SQL%NOTFOUND THEN
          raise_application_error(-20003,'不存在该雇员号');
       end if;
    else
       raise_application_error(-20001,'工资不在范围内');
    end if;
  end;
  
  procedure upd_sal(name varchar2,salary number) is 
  begin
     if salary between minsal and maxsal then
        update emp set sal=salary where upper(ename)=upper(name);
        if SQL%NOTFOUND THEN
           raise_application_error(-20004,'不存在该雇员名');
        end if;
     else
        raise_application_error(-20001,'工资不在范围内');
     end if;
  end;
  
begin
  select min(sal),max(sal) into minsal,maxsal from emp;
end;

--调用包公用组件
--当在同一会话中第一次调用包的公用组件时,会自动执行其构造过程
--而将来调用其他组件时则不会再调用其构造过程,所以构造过程也称为"只调用一次"的过程
exec emp_package.add_employee(1111,'MARY',3000,2)

exec emp_package.upd_sal('mary',2000)

--当工资不在最低工资和最高工资之间时,则会提示错误信息
exec emp_package.upd_sal('mary',5500)

select * from emp;


--使用纯度级别
--当使用包的公用函数时,它既可以作为表达式的一部分使用,也可以在SQL语句中使用。
--但如果要在SQL语句中引用包的公用函数,那么该公用函数不能包含DML语句(INSERT、UPDATE和DELETE),也不能读写远程包的变量。
--为了对包的公用函数加以限制,在定义包规范时可以使用纯度级别(purity level)限制公用函数
--PRAGMA RESTRICT_REFERENCES(function_name,WNDS[,WNPS][,RNDS][,RNPS]);
--如上所示,function_name用于指定已经定义的函数名
--WNDS用于限制函数不能修改数据库数据(也即禁止执行DML操作)
--WNPS用于限制函数不能修改包变量(也即不能给包变量赋值)
--RNDS用于限制函数不能读取数据库数据(也即禁止执行SELECT操作)
--RNPS用于限制函数不能读取包变量(也即不能将包变量赋值给其他变量)

--以下以限制函数不能修改包变量为例,说明使用纯度级别的方法
--建立包规范
--当使用纯度级别限制包的公用函数时,必须首先在包规范中定义函数,然后指定该函数的纯度级别
CREATE OR REPLACE PACKAGE purity IS
  minsal number(6,2);
  maxsal number(6,2);
  function max_sal return number;
  function min_sal return number;
  pragma restrict_references(max_sal,WNPS);
  pragma restrict_references(min_sal,WNPS);
END;

--建立包体
--因为在定义包规范时为函数max_sal和min_sal指定了纯度级别WNPS,所以在这两个函数内不能给变量minsal和maxsal赋值
--错误示例如下
CREATE OR REPLACE PACKAGE BODY purity IS
   function max_sal return number
   is
   begin
      select max(sal) into maxsal from emp;
      return maxsal;
   end;
   
   function min_sal return number
   is
   begin
      select min(sal) into minsal from emp;
      return minsal;
   end;
END;

--尽管在函数体内不能为全局变量minsal和maxsal赋值,但却可以读取它们的数据。
--在函数体内正确引用这两个变量的包体如下
--尽管在函数体内不能修改包变量minsal和maxsal,但却可以读取它们的数据(RETURN语句)
CREATE OR REPLACE PACKAGE BODY purity IS
  FUNCTION max_sal RETURN NUMBER
  IS
  BEGIN
     RETURN maxsal;
  END;
  
  FUNCTION min_sal return number
  is
  begin
     return minsal;
  end;
begin
  select min(sal),max(sal) into minsal,maxsal from emp;
end;

--调用包的公用函数
--在SQL*Plus中引用包的全局变量和包的公用函数的示例如下
var minsal number
var maxsal number
exec :minsal:=purity.minsal
exec :maxsal:=purity.max_sal()
print minsal maxsal

 

分享到:
评论

相关推荐

    Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(一)

     本书是专门为oracle应用开发人员提供的sql和pl/sql编程指南。通过学习本书,读者不仅可以掌握oracle常用工具oracle universal installer、net comfiguration assistant、sql developer、sql*plus的作用及使用方法...

    精通Oracle.10g.PLSQL编程

    br>精通Oracle 10g PL/SQL编程 <br> 【作 者】王海亮 林立新 于三禄 郑建茹 【丛 书 名】 万水Oracle技术丛书 <br>http://images.china-pub.com/ebook20001-25000/21975/shupi.jpg<br><br>PL/SQL是...

    Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(二)

     本书是专门为oracle应用开发人员提供的sql和pl/sql编程指南。通过学习本书,读者不仅可以掌握oracle常用工具oracle universal installer、net comfiguration assistant、sql developer、sql*plus的作用及使用方法...

    Oracle 11g SQL和PL SQL从入门到精通〖送源代码〗

    本书是专门为Oracle应用开发人员提供的SQL和PL/SQL编程指南。通过学习本书,读者不仅可以掌握Oracle常用工具Oracle Universal Installer、Net Comfiguration Assistant、SQL Developer、SQL*Plus的作用及使用方法,...

    精通Oracle.10g.Pl.SQL编程

    而且还提供了相应的习题和答案,对于PL/SQL开发人员,可能已经非常熟悉PL/SQL的基本开发方法,但可能对PL/SQL高级内容(集合类型,对象类型,LOB对象处理)和oracle9i/oracle10g的PL/SQL新特性知之较少,本书对于这些高级...

    Oracle 11g SQL和PL SQL从入门到精通.part1

     本书是专门为oracle应用开发人员提供的sql和pl/sql编程指南。通过学习本书,读者不仅可以掌握oracle常用工具oracle universal installer、net comfiguration assistant、sql developer、sql*plus的作用及使用方法...

    Oracle 11g SQL和PL SQL从入门到精通part2 pdf格式电子书 下载(二)

     本书是专门为oracle应用开发人员提供的sql和pl/sql编程指南。通过学习本书,读者不仅可以掌握oracle常用工具oracle universal installer、net comfiguration assistant、sql developer、sql*plus的作用及使用方法...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

     作为Oracle SQL经典著作之一,本书为SQL开发人员指明了前行的方向,赋予了他们不断开拓的动力。 作者简介  KAREN MORTON 研究人员、教育家及顾问,Fidelity信息服务公司的资深数据库管理员和性能调优专家。她...

    Oracle11g从入门到精通2

    《Oracle11g从入门到精通》面向数据库管理人员和数据库开发人员,从实际角度出发,系统地介绍了数据库和Oracle的相关概念和原理、Oracle的数据库管理(如安装与启动,用户权限、备份与恢复等),以及Oracle的应用...

    Oracle11g从入门到精通

    《Oracle11g从入门到精通》面向数据库管理人员和数据库开发人员,从实际角度出发,系统地介绍了数据库和Oracle的相关概念和原理、Oracle的数据库管理(如安装与启动,用户权限、备份与恢复等),以及Oracle的应用...

    Oracle 11g 从入门到精通

    《Oracle11g从入门到精通》面向数据库管理人员和数据库开发人员,从实际角度出发,系统地介绍了数据库和Oracle的相关概念和原理、Oracle的数据库管理(如安装与启动,用户权限、备份与恢复等),以及Oracle的应用...

    Oracle 11g 从入门到精通.haozip02.7z

    包和Oracle数据库进行案例开发的详细过程。对于初学者,《Oracle11g从入门到精通》是一本很好的入门教程,对Oracle管理员和应用程序 开发员,也有很好的学习和参考价值。  Oracle数据库系统是数据库领域最优秀的...

    精通qt4编程(源代码)

    在三大GUI框架GTK+、Qt和wxWidgets 之间,我们选择了Qt 4工具包。作为重量级桌面系统KDE多年的坚实基础,Qt应该是经受了足够的考验。当我们准备编写自己的应用软件时,却发现图书市场上没有一本关于Qt 4的书籍,仅有...

    Oracle 11g 从入门到精通.haozip01.7z

    包和Oracle数据库进行案例开发的详细过程。对于初学者,《Oracle11g从入门到精通》是一本很好的入门教程,对Oracle管理员和应用程序 开发员,也有很好的学习和参考价值。  Oracle数据库系统是数据库领域最优秀的...

    精通Qt4编程(第二版)源代码

    在三大GUI框架GTK+、Qt和wxWidgets 之间,我们选择了Qt 4工具包。作为重量级桌面系统KDE多年的坚实基础,Qt应该是经受了足够的考验。当我们准备编写自己的应用软件时,却发现图书市场上没有一本关于Qt 4的书籍,仅有...

    精通sql结构化查询语句

    1.5 SQL开发环境 1.5.1 SQL环境介绍 1.5.2 SQL的层次结构 1.5.3 SQL环境中的对象 1.5.4 SQL环境中的程序系统 1.6 SQL语句基础 1.6.1 SQL常量 1.6.2 SQL表达式 1.6.3 SQL数据类型 1.6.4 注释符 1.6.5 批处理 1.6.6 ...

    java从零基础到精通 学习笔记 (带批注) 完整版PDF

    Java应用广泛,涉及个人PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网等...包含内容: Unix,Java 基础,数据库(Oracle jdbc Hibernate pl/sql),web,JSP,Struts,Ajax,Spring,Ejb,Java和模式。

    vc++ 开发实例源码包

    ----------VC应用开发 [Visual.C..编程技巧精选500例]源代码. 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件...

    EfsFrame(php开发框架) 2.2.rar

    EfsFrame是一套整体的企业级php开发框架解决方案,整个框架体系中包含了Web表现层开发包,组件开发包,基础数据库设计一整套完整的基于B/S架构应用程序设计开发的完整解决方案。Efs框架从研发到时间,历时近10年,...

Global site tag (gtag.js) - Google Analytics