Chinaunix首页 | 论坛 | 博客
  • 博客访问: 363659
  • 博文数量: 56
  • 博客积分: 2721
  • 博客等级: 中校
  • 技术积分: 460
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-29 16:18
文章分类

全部博文(56)

文章存档

2014年(1)

2011年(15)

2010年(5)

2008年(35)

分类: 数据库开发技术

2008-08-08 15:22:43

  PL/SQL中的存储过程和函数是用来完成特定功能的子程序。

1.创建存储过程
    存储过程的创建包括参数的定义与过程体的定义两部分。如下是存储过程的一个结构体。
   
    CREATE OR REPLACE PROCEDURE 过程名
    (
      ... --参数定义部分
    ) IS
      ... --局部变量定义部分
    BEGIN
      ... --可执行部分
    EXCEPTION
      ... --异常处理部分
    END 过程名;
   
    如下是一个存储过程的完成事例:
   
    CREATE OR REPLACE PROCEDURE get_happy
    (p_ename_in IN VARCHAR2)
    IS
      hiredate DATE;
    BEGIN
      hiredate := SYSDATE - 2;
      INSERT INTO employee
        (emp_name, hiredate)
      VALUES (p_ename_in, hiredate);
    EXCEPTION
      WHEN DUP_VAL_IN_INDEX
      THEN
        DBMS_OUTPUT.PUT_LINE
          ('Cannot insert.');
    END;
   

   
  1.1 存储过程的参数
   1.1.1存储过程的参数分为实参和形参两种。
    形参也叫形式参数,如上面代码的p_ename_in就是形参。
    如下的代码是对get_happy进行调用:
  
    DECLARE
      v_ename_in employee.emp_name%TYPE := 'Tom';
    BEGIN
      get_happy(v_ename_in);
    END;
   

    上面代码是对get_happy存储过程的调用。其中v_ename_in就是实际参数,也叫实参。
 
   1.1.2在参数的定义中,IN、OUT和IN OUT关键字代表参数的三种不同模式。
    a)IN: 代表输入的参数。即该参数是只读的,如果在传剑存储过程时没有指定参数的模式,则默认为IN。
    b)OUT: 代表输出的参数。即该参数是只写的,只能为其赋值。
    c)IN OUT: 代表既输出又输出的参数。即可读写。
    例如,下面是一个含有三种从那书模式的存储过程:
   
    CREATE OR REPLACE PROCEDURE UpdateAuthsSalary(
      p_Author_code IN OUT auths.author_code%TYPE,
      p_Salary IN NUMBER,
      p_Name OUT auths.name%TYPE
      ) IS
      v_Salary_temp NUMBER; --定义存储过程中的局部变量
    BEGIN
      SELECT salary INTO v_Salary_temp
        FROM AUTHS
        WHERE author_code = p_Author_code;
      --如果该作家的工资小于300元,则修改其中工资
      IF v_Salary_temp < 300 THEN
        UPDATE auths
          SET salary = p_Salary
          WHERE author_code = p_Author_code;
      END IF;
     
      SELECT name
        INTO p_Name
        FROM auths
        WHERE author_code = p_Author_code;
    END UpdateAuthsSalary;
  

    1.1.3参数的数据类型
      我们可以观察一下前面的存储过程,比如
     
      CREATE OR REPLACE PROCEDURE get_happy(
       p_ename_in IN VARCHAR2
       )IS
      
     以及
    
     CREATE OR REPLACE PROCEDURE UpdateAuthsSalary(
      p_Author_code IN OUT auths.author_code%TYPE,
      p_Salary IN NUMBER,
      p_Name OUT auths.name%TYPE
      ) IS
    
    我们会发现 get_happy的p_ename_in的类型为VARCHAR2,VARCHAR2没有指定长度。UpdateAuthsSalary的p_Salary的类型为NUMBER,NUMBER同样没有指定长度。那是因为:
    在定义一个存储过程参数时,不能指定CHAR类型和VARCHAR2类型形参的长度,也不能指定NUMBER形参的精度和标度。这些约束由实参来传递。
   
  1.1.4  参数的传值方式
    在调用存储过程时,有下面两种参数传值方式:
    a)位置表示法
    b)名称表示法
    比如就用调用上面的UpdateAuthsSalary存储过程为例,如下传值方式就是位置表示法。
   
  DECLARE
    v_Author_code VARCHAR2(6) := 'A00001';
    v_Salary IN NUMBER(5) := 350,
    v_Name VARCHAR2(6);
  BEGIN
    UpdateAuthsSalary(v_Author_code, v_Salary, v_Name);
  END;
  

  如下传值方式就是名称表示法。
  
  DECLARE
    v_Author_code VARCHAR2(6) := 'A00001';
    v_Salary IN NUMBER(5) := 350,
    v_Name VARCHAR2(6);
  BEGIN
    UpdateAuthsSalary(
      p_Author_code => v_Author_code,
      p_Salary => v_Salary,
      p_Name => v_Name);
  END;
  

  也可以混合使用,但是,当在调用存储过程中出现了第一个命名表示法的参数时,后面的参数也必须使用命名表示法传值。如下:
  
  DECLARE
    v_Author_code VARCHAR2(6) := 'A00001';
    v_Salary IN NUMBER(5) := 350,
    v_Name VARCHAR2(6);
  BEGIN
    UpdateAuthsSalary(v_Author_code,
      p_Name => v_Name,
      p_Salary => v_Salary);
  END;


2.创建函数

   如下是函数的结构体。
   
    CREATE OR REPLACE FUNCTION 函数名
    (
      ... --参数定义部分
    ) RETURN 返回类型 IS
      ... --局部变量定义部分
    BEGIN
      ... --可执行部分
    EXCEPTION
      ... --异常处理部分
    END 过程名;
   

  与存储过程一样,参数列表是可选的。在没有参数的情况下,函数的定义与调用都没有圆括号。但返回值类型是必须的,因为函数是作为表达式的一部分调用,必须返回一个值。如下是一个函数的完整的例子:
 
  CREATE OR REPLACE FUNCTION company_type (
   p_type_code_in IN VARCHAR2)
   RETURN VARCHAR2
 IS
   v_return_value VARCHAR2 (25) := NULL;
 BEGIN
    IF p_type_code_in = 'S'
    THEN
       v_return_value := 'SUBSIDIARY';
 
    ELSIF p_type_code_in = 'P'
    THEN
       v_return_value := 'PARTNER';
    END IF;
 
    RETURN v_return_value;
 END;

  可以利用下面的块来调用上面的函数:
  DECLARE
    v_type_code_in VARCHAR2(1);
    v_company_type VARCHAR2(50);
  BEGIN
    v_type_code_in := 'P';
    v_company_type := company_type(v_type_code_in);
    DBMS_OUTPUT.PUT_LINE(v_company_type);
  END;

阅读(1369) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-07-21 15:54:00

r