侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

数据库  /  管理员 发布于 5年前   298

/* *开发包 *包用于逻辑组合相关的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 numberexec :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 PACKAGEDROP 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 numbervar sal2 numberexec :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 numbervar maxsal numberexec :minsal:=purity.minsalexec :maxsal:=purity.max_sal()print minsal maxsal

 


  • 上一条:
    精通Oracle10编程SQL(11)开发子程序
    下一条:
    精通Oracle10编程SQL(13)开发触发器
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客