Oracle就业课第四课之子程序

    科技2022-07-12  139

    4、子程序

    回顾

    练习:

    declare v_name emp.ename%type:='张三'; v_job emp.job%type:='游客'; begin for n in 1..3 loop insert into emp(empno,ename,job,mgr,hiredate,sal,deptno) values(n*10,v_name||n,v_job,8000,to_date('2020-9-16','yyyy-MM-dd'),16000,10); end loop; commit; --提交事务 exception when others then rollback; --回滚事务 end;

    学习目标

    1、子程序

    2、存储过程

    3、函数

    4、包

    学习内容

    1、子程序

    plsql:过程化的sql语言;变量、常量、匿名块、分支语句、循环语句

    子程序:命名的程序块,存储过程 和 函数。

    2、存储过程

    分析:完成一些指定的业务,单一的命令无法搞定;比如:转账,分页操作

    存储过程:类似于java中的方法,通过多条sql命令,完成一个特定的任务。

    优点:

    1、执行效率高:预编译的,存储在服务器上,第一次创建好,系统会进行预编译;

    2、减少网络流量:代码封装到过程中,只需要调用过程名就行。

    3、安全性:A:小明 B:小红 C:小青

    4、重用性:代码角度考虑。

    存储过程中能写的命令:

    1、insert,update,delete,select …into 变量

    2、过程控制命令(条件、循环)

    3、不能写DDL

    使用存储过程

    1、定义过程

    -- 创建过程 procedure:过程 create or replace procedure sp_test1( -- 参数 ) as -- 声明部分 (临时变量:过程中使用的变量) begin exception end;

    2、调用过程

    1 call 过程名(参数); 2、 begin 过程名(参数); end; 3、sqlplus: execute 过程名();

    栗子:

    1、转账:无参数

    create or replace procedure sp_zhuanzhang as v_money bank.balance%type:=1000; --要转账的钱数 begin update bank set balance=balance-v_money where name='李四'; update bank set balance=balance+v_money where name='张三'; commit; exception when others then rollback; end;

    调用:

    call sp_zhuanzhang(); begin sp_zhuanzhang; end;

    2、转账:带参数

    --flag :1 :张三---》李四 2:李四 --->张三 钱数 create or replace procedure sp_zhuanzhang2 ( --输入参数 --参数名 数据类型(变量声明) flag in number, money in number ) as begin if flag=1 then update bank set balance=balance-money where name='张三'; update bank set balance=balance+money where name='李四'; else update bank set balance=balance-money where name='李四'; update bank set balance=balance+money where name='张三'; end if; commit; exception when others then rollback; end;

    调用:

    declare flag number(1):=2; money number(5):=500; begin sp_zhuanzhang2(flag,money); end;

    3、转账:带输入和输出参数

    create or replace procedure sp_zhuanzhang3 ( --输入参数 --参数名 数据类型(变量声明) flag in number, money in number, --输出参数:调用过程后,可以在外部获取到值的数据:类似于返回值,可以有多个 balance1 out bank.balance%type, balance2 out bank.balance%type ) as begin if flag=1 then update bank set balance=balance-money where name='张三'; update bank set balance=balance+money where name='李四'; else update bank set balance=balance-money where name='李四'; update bank set balance=balance+money where name='张三'; end if; commit; select balance into balance1 from bank where name='张三'; select balance into balance2 from bank where name='李四'; exception when others then rollback; end;

    调用:

    declare --声明变量:用来接受输出参数的值 b1 bank.balance%type; b2 bank.balance%type; begin sp_zhuanzhang3(2,1000,balance2=>b1,balance1=>b2); dbms_output.put_line('张三:'||b2||'李四:'||b1); end;

    过程调用中的参数传递

    1、按照位置传递

    2、按照名字传值:顺序无关

    参数名=>变量 参数名=>变量 参数名=>变量

    3、组合传递

    ​ 位置传递+名字传递;位置传递(靠前)

    3、函数

    本质上跟过程一样:必须有返回值

    定义函数:

    create or replace function 名字( -- 参数 --名字 类型 ) return 数据类型 as begin return 结果; end;

    例子:

    1、根据部门编号查询部门名称

    create or replace function f_getDname( -- 传入参数 :部门编号 dno dept.deptno%type ) return varchar2 --返回字符串 as v_name dept.dname%type; begin select dname into v_name from dept where deptno=dno; return v_name; --返回结果 end; --调用 select empno,ename,deptno,f_getdname(deptno) 部门 from emp where f_getdname(deptno)='外交部';

    2、根据部门编号统计部门人数

    create or replace function f_getdeptcount( --参数 dno number )return number as v_count number(5); begin select count(*) into v_count from emp where deptno=dno; return v_count; end; --调用 select deptno,dname,f_getdeptcount(deptno) 人数 from dept;

    3、生成随机数字的函数

    create or replace function getrandomvalue return number as n number(20); begin n:=dbms_random.value(1,10); return n; end; --调用 select getrandomvalue() from dual ;

    调用:

    declare n number(5); begin n:=getrandomvalue(); dbms_output.put_line(n); end;

    4、包

    包:package

    一系列的过程和函数

    可以根据业务的不同创建不同的包:声明变量+过程+函数;

    包:

    1、包规范:类似于java中的接口

    2、包体:类似于实现类

    创建包规范:

    create or replace package 名字 is --声明 变量 过程 函数 end 名字;

    创建包体:

    create or replace package body 名字 is --实现包规范定义好的过程和函数 end;

    栗子:

    create or replace package myfirstpackage is --声明 全局的变量 dno dept.deptno%type; --过程:向员工表中录入数据,不能录入重名的 procedure add_emp(vno in number,vname in varchar2); --过程:根据部门编号,删除部门信息,只能删除没有员工的部门 procedure del_dept(vno in number); end package; --包体 create or replace package body myfirstpackage is --过程实现 procedure add_emp(vno in number,vname in varchar2) as v_count number(2);-- 满足条件的员工的数量 begin select count(*) into v_count from emp where ename=vname; if v_count>0 then --提示错误消息 --dbms_output.put_line(''); --raise_appliction_error:抛出一个自定义的错误消息,错误号:-20000- raise_application_error(-20001,'名字重复'); else insert into emp(empno,ename) values(vno,vname); commit; end if; end; --过程实现:根据部门编号,删除部门信息,只能删除没有员工的部门 procedure del_dept(vno in number) as v_count number(3); begin --根据部门编号查询该部门对应的人数 select count(*) into v_count from emp where deptno=vno; if v_count=0 then delete from dept where deptno=vno; commit; else raise_application_error(-20002,'该部门下有员工,无法删除'); end if; end; end myfirstpackage;

    总结

    1、存储过程

    2、函数

    相同点:

    1、预编译、执行效率高、安全性、减少网络流量

    2、输入参数、输出参数

    不同点:

    1、函数必须指定return(返回值)

    3、包:包规范和包体(实现);

    tea_year 认证博客专家 大司徒 产品总监 微软MVP!ORACLE认证高级工程师!主要研究方向为大数据、人工智能、JAVA、.Net、数据库 、前端开发、产品研发,曾经服务过中铝、中烟等大型上市国企IT部门,软件企业联合创始人,喜欢软件研发管理、技术营销!
    Processed: 0.015, SQL: 8