oracle存储过程和函数

 

--第五节课内容

     --可以用预编译命令给我们的自定义异常绑定编号
     --自定义异常的编号范围-20000~-20999
     Pragma  Exception_Init(异常名,异常编号)
    
------------------------------------------------------------------------------------------------
Declare
 Too_Many_People Exception;
  Pragma Exception_Init(Too_Many_People,-20001);
 No_Such_Dept Exception;
  Pragma Exception_Init(No_Such_Dept,-20002);

Begin
 Update Emp Set Sal = Sal + 100 Where Deptno = &p_Deptno;
 If Sql%Rowcount > 5 Then
  Raise Too_Many_People;
 Elsif Sql%Notfound Then
  Raise No_Such_Dept;
 End If;

 --commit;
 Dbms_Output.Put_Line('操作成功');
Exception
 When Too_Many_People Then
  Dbms_Output.Put_Line('部门人数过多');
    Dbms_Output.Put_Line(Sqlcode);
    Dbms_Output.Put_Line(Sqlerrm);
  Rollback;
 When No_Such_Dept Then
  Dbms_Output.Put_Line('部门编号不合法或部门无员工');
    Dbms_Output.Put_Line(Sqlcode);
    Dbms_Output.Put_Line(Sqlerrm);
  Rollback;
End;
/
-------------------------------------------------------------------------------------------
                                                             
     --绑定描述
     --将异常编号和异常描述绑定抛出
     --异常描述最长可以支持2048个字符
     --异常编号不需要绑定名字
     raise_application_error(异常编号,异常描述);
-------------------------------------------------------------------------------------------
Begin
 Update Emp Set Sal = Sal + 100 Where Deptno = &p_Deptno;
 If Sql%Rowcount > 5 Then
  Raise_Application_Error(-20001, '部门人数过多'); --绑定描述
 Elsif Sql%Notfound Then
  Raise_Application_Error(-20002, '部门编号不合法或部门无员工');
 End If;

 --commit;
 Dbms_Output.Put_Line('操作成功');
Exception
  When Others Then
    Dbms_Output.Put_Line(Sqlcode);
  Dbms_Output.Put_Line(Sqlerrm);
End;
/
------------------------------------------------------------------------------------------


第六章  子程序
子程序:有名字的PL/SQL块。可以被当做对象存储在数据库当中,通常可以接收参数,被别人调用执行。
        符合PL/SQL块的标准结构。
    
一、存储过程
    通常用来完成某项复杂的操作
   1.创建语法
     Create [Or Replace] Procedure 存储过程名[(参数列表)]
     Is|As
       --声明部分,不用写declare关键字
     Begin
    
     Exception
    
     End [存储过程名];--建议加上存储过程名,增加程序的可读性
    
     --参数列表
       参数名1 [参数模式] 数据类型1,参数名2 [参数模式] 数据类型2,...参数名n [参数模式] 数据类型n
       a.参数的数据类型只写类型名,不能加长度;
       b.参数模式:in模式,out模式,in out模式。默认为in模式;
      
    2.如何编辑和编译存储过程
       a.可以在SQL-window中编辑,全选,按F8键编译
       b.可以在command-window中编辑,用/来编译,用show errors命令查看编译错误
       c.可以使用向导。
      
练习:写一个存储过程,输出Hello World!
Create Or Replace Procedure print_procedure
As
Begin
     dbms_output.put_line('Hello World');
End print_procedure;
   
   
    3.如何调用存储过程
      a.在另一块中调用 print_procedure;
      b.在SQL/PLUS环境中,使用exec环命令调用
         Exec 存储过程名字(参数列表)
------------------------------------------------------------------------------------------------

C:\Documents and Settings\ttc>sqlplus scott/tiger

SQL*Plus: Release 10.2.0.1.0 - Production on 星期一 2月 28 15:07:31 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


连接到:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> set serveroutput on
SQL> exec print_procedure;
Hello World

PL/SQL 过程已成功完成。
-----------------------------------------------------------------------------------------------

练习:写一个存储过程,根据参数传入的员工编号,输出员工的姓名和工资

Create Or Replace Procedure put_ename(p_empno emp.empno%Type)
Is
 v_ename emp.ename%Type;
 v_sal emp.sal%Type;
Begin
     Select ename,sal
     Into v_ename,v_sal
     From emp
     Where empno=p_empno;
     --p_empno:7788;错误
    
     dbms_output.put_line(v_ename || ' ' ||v_sal);
 
Exception
     When no_data_found Then
        dbms_output.put_line('没有数据'); 
End put_ename;
------------------------------------------------------
Begin
     put_ename(&p_empno);
End;
/
--------------------------------------------------------

   4.参数模式
     a.In 模式:调用环境向存储过程内部传递参数,in模式的参数在存储过程内部被当做一个常量来使用。
                In 模式的参数可以设定默认值。
               
Create Or Replace Procedure put_ename(p_empno emp.empno%Type Default 7788)
Is
 v_ename emp.ename%Type;
 v_sal emp.sal%Type;
Begin
     Select ename,sal
     Into v_ename,v_sal
     From emp
     Where empno=p_empno;
     --p_empno:7788;错误
    
     dbms_output.put_line(v_ename || ' ' ||v_sal);
 
Exception
     When no_data_found Then
        dbms_output.put_line('没有数据'); 
End put_ename;
------------------------------------------------------
--调用
Begin
     put_ename();--这是不传参数,会自动查处数据,利用默认值
End;
/
--------------------------------------------------------
    
      b.Out 模式:由存储过程内部向调用环境传值。out模式的参数在存储过程内部当做一个变量来使用
                  out模式的实参一定是一个变量
       --存储过程没有返回值,在存储过程内部,一定不能够出现return语句;
       --存储过程可以使用out模式的参数向调用环境传值
       --给out模式参数赋予什么值,调用环境就会接收一个什么值
    
练习:写一个存储过程,根据参数传入的员工编号,返回员工的姓名和工资
Create Or Replace Procedure Get_Ename(p_Empno Emp.Empno%Type, p_Ename Out Emp.Ename%Type, p_Sal Out Emp.Sal%Type) Is
Begin
 Select Ename, Sal Into p_Ename, p_Sal From Emp Where Empno = p_Empno;
Exception
 When No_Data_Found Then
  p_Ename := 'not found';
  p_Sal   := 0;
End Get_Ename;
-----------------------------------------------------------------
--调用
Declare
 v_Ename Emp.Ename%Type; --声明变量接收
 v_Sal   Emp.Sal%Type;
Begin
 Get_Ename(&p_Empno, v_Ename, v_Sal);

 Dbms_Output.Put_Line(v_Ename || ' ' || v_Sal);
End;
/
-----------------------------------------------------------------

     c.In Out 模式:既能传入又能传出的参数。 in Out 模式参数的实参一定是一个有值的变量。
    
练习:写一个存储过程,根据员工编号和工资的涨幅,更新emp表,要求返回员工修改后的工资
Create Or Replace Procedure Emp_Procedure(p_Empno Emp.Empno%Type, p_Sal In Out Emp.Sal%Type) Is
Begin
 Update Emp Set Sal = Sal + p_Sal Where Empno = p_Empno;
 Select Sal Into p_Sal From Emp Where Empno = p_Empno;
Exception
 When No_Data_Found Then
  Dbms_Output.Put_Line('没有数据');
    Rollback;
End Emp_Procedure;
---------------------------------------------------------------
--调用
Declare
       v_sal emp.sal%Type;
Begin
     v_sal:=200;
     Emp_Procedure(&p_empno,v_sal);
     dbms_output.put_line(v_sal);
End;
/
---------------------------------------------------------------

   5.参数传递方式
     a.按照位置传参
        Get_Ename(&p_Empno, v_Ename, v_Sal);
     b.按照名称传参
         Emp_Procedure(p_Sal=>v_Sal,p_Empno=>7788);--形参名字=>实参名字
     c.按照混合方式传参
         前面使用位置传参,后面用名字传参
         Get_Ename(&p_Empno, p_Sal=>v_Sal,p_Ename=>v_Ename);
        
   6.本地子程序(见课件)--本地子程序一定是声明部分的最后一个元素
   7.删除存储过程
     Drop Procedure 存储过程名;
     Drop Procedure  print_procedure;
     
   
二、函数
    函数有返回值,通常用来做某些计算。
    函数的内部至少要含有一个return语句。
    函数可以作为表达式的一部分调用。
    Select Sysdate +7 From dual;--当前日期加七天
   
    1.函数的创建语法
      Create [Or Replace] Function 函数名[(参数列表)]
      Return 数据类型--定义了函数的返回值类型,函数的声明必须要有return子句
      Is|As
           --声明部分,不用写declare
      Begin
     
      Exception
     
      End [函数名];
     
      --参数列表的定义和存储过程一样
     
    2.如何编辑和编译
      --参照存储过程
     
练习:写一个函数,根据员工的编号,返回年薪(考虑comm)
Create Or Replace Function Get_Sal(p_Empno Emp.Empno%Type) Return Number As
 v_Annsal Number;
Begin
 Select (Sal + Nvl(Comm, 0)) * 12 Into v_Annsal From Emp Where Empno = p_Empno;
 Return v_Annsal;
Exception
 When No_Data_Found Then
  Return 0;
End Get_Sal;

    3.调用环境
      a.在另一个块中调用
        变量:=函数名(参数列表);
------------------------------------------------------------------------------
Declare
       v_sal emp.sal%Type;
Begin
     v_sal:=Get_Sal(&p_empno);
     dbms_output.put_line(v_sal);
End;
/
--------------------------------------------------------------------------------
      b.在SQLplus环境中调用
      Exec :变量:=函数名(参数列表);--外部变量
-------------------------------------------------------------------------------
Sql> Set serveroutput On;
SQL> variable g_annsal number;
SQL> exec:g_annsal:=get_sal(1000);

PL/SQL 过程已成功完成。

SQL> print g_annsal;

  G_ANNSAL
----------
     10560

-------------------------------------------------------------------------------

      c.在SQL语句中调用
        Select,Where,Order By,Group By
        insert语句的values子句中调用
        update语句的set子句中调用
     
      Select ename,sal,get_sal(empno)
      From emp
      Where get_sal>30000
      Order By get_sal(empno);
     
    4.函数的使用限制
      a.在sql语句中调用的函数,只能含有in 模式的参数,不能含有out或者in Out 模式的函数
      b.在sql语句中调用的函数,只能使用Oracle Sql 的标准的数据类型,不能使用PL/SQL特有的数据类型;
        (记录、表、布尔)
      c.在sql语句中调用的函数,不能包含 insert\Update\Delete 语句(Dml)
      d.在update或者delete某个表的操作中,调用的函数内部,不能够查询同一张表
     
    5.删除函数
      Drop Function 函数名;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值