学习PL/SQL之七:子程序

关于子程序:
   子程序是指被命名的PL/SQL块,这种块可以带有参数,可以在不同应用程序中多次调用。
   PL/SQL有两种类型的子程序:过程和函数。过程用于执行特定操作,而函数用于返回特定数据。
开发过程:PROCEDURE
  创建过程
  CREATE [OR REPLACE] PROCEDURE proc_name
   [ (arg_name [ { IN | OUT | IN OUT } ] TYPE,
    …
     arg_name [ { IN | OUT | IN OUT } ] TYPE) ]
   { IS | AS }
  procedure_body
  ……
  OR REPLACE:如果要创建的过程存在,则覆盖或者替换它。
    Procedure_body:是一个带有声明段、可执行段和异常处理段的PL/SQL语句块
  PROCEDURE中定义的要传的参数( arg_name )叫做形式参数,具体调用该PROCEDURE时( proc_name (1,’Johnson’))传进去的参数叫做实际参数。
    IN
      在调用过程的时候,实际参数的值被传递给该过程;在过程内部,形参是只可读的。
    OUT
      在调用过程时,任何的实参将被忽略(必须要在过程内部赋值);在过程内部,形参是只可写的。过程结束时,控制会返回给控制环境,而形式参数的内容将赋给调用时的实际参数。
   IN OUT
      是IN与OUT的组合。在调用过程的时候,实参的值可以被传递给该过程;在过程内部,形参也可以被读出也可以被写入;过程结束时,控制会返回给控制环境,而形式参数的内容将赋给调用时的实际参数。
   参数的缺省模式是IN
   CREATE OR REPLACE PROCEDURE ModeTest(
  p_InParm IN NUMBER := 10 ,
  p_OutParm OUT NUMBER,
  p_InOutParm IN OUT NUMBER)
 IS
  v_LocalVar NUMBER;
 BEGIN
   v_LocalVar := p_InParm;   --legal
   p_InParm := 7;   --illegal
   p_OutParm := 7;  --legal
   v_LocalVar := p_OutParm;  --Possibly illegal
   v_LocalVar := p_InOutParm; --legal
   p_InOutParm := 5;  --legal
   …
  EXCEPTION
   WHEN OTHERS THEN
    …
 END ModeTest;
 模式为IN OUT或OUT参数对应的实际参数必须是变量,不能是常量或表 达式。因为必须要有一个位置(即传进去的那个变量)可以存储返回的                    值(见callMT.sql)
  模式为IN可以传常量也可以传变量
  形式参数不能声明约束(如:不能指定缓冲区的大小),但可使用%TYPE来进行约束
  在调用过程当中,实际参数在将值传递给过程时,也传递了对变量的约束。
   -- illegal
 CREATE OR REPLACE PROCEDURE ParameterLength (
    p_Parameter1 IN OUT VARCHAR2(20), --illegal with VARCHAR2(10)
    p_Parameter2 IN OUT NUMBER(3,1)) AS --illegal with NUMBER(3,1)
 BEGIN
    p_Parameter1 := 'abcdefghijklm';
    p_Parameter2 := 12.3;
 END ParameterLength;
 /
 
 -- Legal
 CREATE OR REPLACE PROCEDURE ParameterLength (
    p_Parameter1 IN OUT VARCHAR2,
    p_Parameter2 IN OUT NUMBER) AS
 BEGIN
    p_Parameter1 := 'abcdefghijklm';
    p_Parameter2 := 12.3;
    dbms_output.put_line('p_Parameter1 :'||p_Parameter1);
    dbms_output.put_line('p_Parameter2 :'||p_Parameter2);
 END ParameterLength;
 /
 
 DECLARE
    v_Variable1 VARCHAR2(40);
    v_Variable2 NUMBER(7,3);
 BEGIN
    ParameterLength(v_Variable1, v_Variable2);
 END;
 /
 
 DECLARE
    v_Variable1 VARCHAR2(10);--illegal,'abcdefghijklm'.lenth > 10
    v_Variable2 NUMBER(7,3);--legal
 BEGIN
    ParameterLength(v_Variable1, v_Variable2);
 END;
 /
指定实参的模式 
  位置标示法
    调用时添入所有参数,实参与形参按顺序一一对应
  名字标示法
     调用时给出形参名字(顺序不要求一一对应),并给出实参
     ModeTest(p_InOutParameter  => v_var2,
      p_OutParameter => v_var1,
     p_InParameter => 10);
  两种方法可以混用
   混用时,第一个参数必须通过位置来指定
   名字标示法对于参数很多时,可提高程序的可读性
  
   CREATE OR REPLACE PROCEDURE ModeTest(
   p_In IN NUMBER,
   p_Out IN NUMBER,
   p_inout IN NUMBER)
  IS
   v_Local Number;
  BEGIN
   --DBMS_OUTPUT.Enable;
   v_Local := p_In;
   DBMS_OUTPUT.PUT_LINE( '1--> '||V_LOCAL|| ' 2--> '||P_OUT||' 3--> '||P_INOUT);
  END ModeTest;
  /
  
  DECLARE
   A NUMBER;
   B NUMBER;
   C NUMBER;
  BEGIN
   A := 5;
   B := 6;
   C := 7;
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
   ModeTest(A,B,C);
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
  END;
  /
  
  DECLARE
   A NUMBER;
   B NUMBER;
   C NUMBER;
  BEGIN
   A := 5;
   B := 6;
   C := 7;
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
   ModeTest(p_In => C,p_INOUT => B, p_Out => A);
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
  END;
  /
  
  DECLARE
   A NUMBER;
   B NUMBER;
   C NUMBER;
  BEGIN
   A := 5;
   B := 6;
   C := 7;
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
   ModeTest( C,p_INOUT => B, p_Out => A);
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
  END;
  /
  
  
  DECLARE
   A NUMBER;
   B NUMBER;
   C NUMBER;
  BEGIN
   A := 5;
   B := 6;
   C := 7;
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
   ModeTest( p_In => C,B,A);--illegal
   DBMS_OUTPUT.PUT_LINE(' A = ' || A || ' ,B = ' || B || ' ,C = ' || C);
  END;
  /
  
  
开发函数
  CREATE [OR REPLACE] FUNCTION func_name
  [ (arg_name [ { IN | OUT | IN OUT } ] TYPE,
   …
  (arg_name [ { IN | OUT | IN OUT } ] TYPE )]
  RETURN TYPE
 { IS | AS }
  Func_body
  在函数的主体内部,return语句用来将控制通过一个数值(或其他返回类型)返回给调用环境,且返回类型都不能加上约束。
RETURN <类型>;
  在一个函数主体中,可以使用多个返回语句,只有一个会被执行
  没有返回语句的函数将是一个错误
  CREATE OR REPLACE FUNCTION ClassInfo(
    p_Department classes.department%TYPE,
    p_Course classes.course%TYPE)
    RETURN VARCHAR2 IS
 
    v_CurrentStudents NUMBER;
    v_MaxStudents NUMBER;
    v_PercentFull NUMBER;
 BEGIN
    SELECT current_students,max_students
      INTO v_CurrentStudents, v_MaxStudents
      FROM classes
      WHERE department = p_Department
      AND course = p_Course;
 
      v_PercentFull := v_CurrentStudents /v_MaxStudents * 100;
 
      IF v_PercentFull = 100 THEN
         RETURN 'Full';
      ELSIF v_PercentFull > 80 THEN
         RETURN 'Some Room';
      ELSIF v_PercentFull > 60 THEN
         RETURN 'More Room';
      ELSIF v_PercentFull > 0 THEN
         RETURN 'Lots of Room';
      ELSE
         RETURN 'Empty';
      END IF;
 END ClassInfo;
  /
  函数可以通过OUT参数来返回多个数值
  函数可以接收缺省参数
函数调用限制
  因为函数必须要返回数据,所以只能作为表达式的一部分调用,另外,函数也可以在SQL语句的一下部分调用:
   1、SELECT 命令的选择列表;
   2、WHERE 和 HAVING 字句中
   3、CONNECT BY,START WITH,ORDER BY 以及GROUP BY字句中。 
   4、INSERT 命令的VALUES字句中
   5、UPDATE 命令的SET子句中
  注意:并不是所有的函数都可以在SQL语句中调用,在SQL语句中调用函数有一下一些限制:
    1、在SQL 语句中只能调用存储函数(服务器端),而不能调用客户端的函数;
    2、在SQL 语句中调用的函数只能带有输入参数(IN),而不能带有输出参数(OUT)和输入输出参数(IN OUT)
    3、在SQL语句中调用的函数只能使用SQL所支持的标准数据类型,而不能使用PL/SQL特有的数据类型(例如:BOOLEAN TABLE,VARRAY)
    4、在SQL语句中调用的函数不能包含INSERT UPDATE DELETE语句

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值