好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Oracle在PL/SQL中使用存储过程

一、概述

过程和函数统称为PL/SQL子程序,他们是被命名的PL/SQL块,均存储于数据库中。

并通过输入、输出和输入输出参数与其调用者交换信息。唯一区别是函数总向调用者返回数据。

二、存储过程详解

1、创建过程语法:

?

1

2

3

4

5

CREATE [ OR REPLACE ] PROCEDURE [ schema . ] procedure_name

     [ ( parameter_declaration [, parameter_declaration ]... ) ]

     [ invoker_rights_clause ]

     { IS | AS }

     { [ declare_section ] body | call_spec | EXTERNAL} ;

说明:

procedure_name:过程名称。 parameter_declaration:参数声明,格式如下:

?

1

2

parameter_name [ [ IN ] datatype [ { := | DEFAULT } expression ]

           | { OUT | IN OUT } [ NOCOPY ] datatype

IN:输入参数。 OUT:输出参数。 IN OUT:输入输出参数。 invoker_rights_clause:这个过程使用谁的权限运行,格式:

?

1

AUTHID { CURRENT_USER | DEFINER }

declare_section:声明部分。 body:过程块主体,执行部分

2、创建存储过程

带有输入、输出参数的过程

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

CREATE OR REPLACE PROCEDURE proc_demo

(

     dept_no NUMBER DEFAULT 10,

     sal_sum OUT NUMBER,

     emp_count OUT NUMBER

   )

IS

BEGIN

     SELECT SUM (salary), COUNT (*) INTO sal_sum, emp_count

   FROM employees WHERE department_id = dept_no;

EXCEPTION

    WHEN NO_DATA_FOUND THEN

       DBMS_OUTPUT.PUT_LINE( '温馨提示:你需要的数据不存在!' );

    WHEN OTHERS THEN

       DBMS_OUTPUT.PUT_LINE(SQLCODE|| '---' ||SQLERRM);

END proc_demo;

3、调用存储过程

调用方式: 
1)、当在SQL*PLUS中调用过程时,需要使用CALL或者EXECUTE命令,而在PL/SQL块中过程可以直接引用。

?

1

2

3

4

5

-- 调用删除员工的过程

EXEC remove_emp(1);

  

-- 调用插入员工的过程

EXECUTE insert_emp(1, 'tommy' , 'lin' , 2);

2)、在PL/SQL语句块中直接调用。

?

1

2

3

4

5

6

7

8

9

DECLARE

V_num NUMBER;

V_sum NUMBER(8, 2);

BEGIN

   Proc_demo(30, v_sum, v_num);

      DBMS_OUTPUT.PUT_LINE( '温馨提示:30号部门工资总和:' ||v_sum|| ',人数:' ||v_num);

   Proc_demo(sal_sum => v_sum, emp_count => v_num);

      DBMS_OUTPUT.PUT_LINE( '温馨提示:10号部门工资总和:' ||v_sum|| ',人数:' ||v_num);

END ;

4、C# 调用:

?

1

2

3

4

5

6

7

OracleCommand cmd = new OracleCommand( "prroc_demo" , myOracleConnection);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add( "v_companycode" , OracleType.Char);

cmd.Parameters[ "v_companycode" ].Value = "aa" ;

cmd.Parameters.Add( "v_returnvalue" , OracleType.Float).Direction = ParameterDirection.Output;

cmd.ExecuteNoQuery();

string eval = cmd.Parameters[ "v_returnvalue" ].Value.ToString();

三、存储过程返回记录集SYS_REFCURSOR

cursor与REF cursor大致有以下几点区别:

静态游标不能返回到客户端,只有PL/SQL才能利用它。ref游标则可以,是从Oracle的存储过站返回结果集的方式。 PL/SQL静态游标可以是全局的,而ref游标只能在定义它的过程中使用,但ref游标可以从子例程传递到子例程,而普通游标则不能。 静态光标比ref游标效率要高。 sys_refcursor在oracle9i以后系统定义的一个refcursor,主要用于在过程中返回结果集。

1、返回单行语法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

create or replace procedure proc_query_rent (

   param_region varchar2,  --定义区

   param_room number,  --定义室

   param_hall number,  --定义厅

   param_rentMin number,  --定义租金上限

   param_rentMax number,  --定义租金下限

   param_resultSet OUT SYS_REFCURSOR --定义out参数返回结果集

)

as

begin

open param_resultSet for select   * from tb_rent

  where region like case when param_region IS null then '%' else param_region end

   AND room like case when param_room IS null then '%' else to_char(param_room) end

   AND hall like case when param_hall IS null then '%' else to_char(param_hall) end

   AND rent between case when param_rentMin IS null then 0 else param_rentMin end

   AND case when param_rentMax IS null then 99999999 else param_rentMax end ;

end ;

调用:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

declare

   v_rent_rows SYS_REFCURSOR;

   v_rent_row tb_rent % rowType;

begin

    proc_query_rent( '山区' , null , null , 1200, null , v_rent_rows);

    Dbms_output.put_line( '所在区 室 厅 租金' );

    loop

       fetch v_rent_rows into v_rent_row;//单行

       exit when v_rent_rows % NOTFOUND;

       Dbms_output.put_line(v_rent_row.region || '  ' || v_rent_row.room || '  ' || v_rent_row.hall || '  ' || v_rent_row.rent);

    end loop;

    close v_rent_rows;

end ;

2、返回多行语法

存储过程:

?

1

2

3

4

5

6

7

8

9

create or replace procedure getEmpByDept(in_deptNo in emp.deptno%type,  out_curEmp out SYS_REFCURSOR) as

begin

  open out_curEmp for

   SELECT * FROM emp WHERE deptno = in_deptNo ;

EXCEPTION

  WHEN OTHERS THEN

  RAISE_APPLICATION_ERROR(-20101,

   'Error in getEmpByDept' || SQLCODE );

end getEmpByDept;

调用(执行存储过程):

?

1

2

3

4

5

6

7

8

9

10

11

12

declare

   cur_emp sys_refcursor;

   type emp emp_type is table of yemp%rowtype;

   vemps emp_type;

begin

    sp_getEmp(line=> 'A5' ,curemp=>cur_emp);

    fetch cur_emp bulk collect into vemps;

    for i in v_emps. first ..v_emps. last loop

       dbms_output.putline(v_emps(i).empid);

    end loop;

    close cur_emp;

end ;

C# 调用:

?

1

2

3

4

5

6

7

8

OracleCommand cmd = new OracleCommand( "prroc_demo" , myOracleConnection);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add( "v_companycode" , OracleType.Char).Value = "aa" ;

cmd.Parameters.Add( "curEmp" , OracleType.Cursor).Direction = ParameterDirection.Output;

OracleDataAdapter da = new OracleDataAdapter(cmd);

DataSet ds = new DataSet();

da.Fill(ds);

this .dataGridView1.DataSource = ds.Tables[0];

四、维护存储过程

1、删除过程

可以使用DROP PROCEDURE命令对不需要的过程进行删除

?

1

DROP PROCEDURE logexecution;

2、显示过程代码

?

1

select text from user_source where name = '存储过程名(大写)' and type= 'PROCEDURE' ;

3、查看过程状态

?

1

select   object_type ,object_name ,status from user_objects where   object_name  = 'procedure' ;

4、重新编译过程

?

1

alter procedure pro_backup compile;

五. 过程与函数比较

1、相同点:

都使用IN模式的参数传入数据、OUT模式的参数返回数据。 输入参数都可以接受默认值,都可以传值或传引导。 调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。 都有声明部分、执行部分和异常处理部分。 其管理过程都有创建、编译、授权、删除、显示依赖关系等。

2、不同点:

过程:作为PL/SQL语句执行;函数:作为表达式的一部分执行 过程:在规范中不包含RETURN子句;函数:必须在规范中包含RETURN子句 过程:不返回任何值;函数:必须返回单个值 过程:可以RETURN语句,但是与函数不同,它不能用于返回值;函数:必须包含至少一条RETURN语句

六、 与过程相关数据字典

USER_SOURCE, ALL_SOURCE, DBA_SOURCE, USER_ERRORS,

ALL_PROCEDURES,USER_OBJECTS,ALL_OBJECTS,DBA_OBJECTS

相关的权限:

?

1

2

3

CREATE ANY PROCEDURE

 

DROP ANY PROCEDURE

SQL*PLUS 中,可以用DESCRIBE 命令查看过程的名字及其参数表。

?

1

DESC [RIBE] Procedure_name;

到此这篇关于Oracle在PL/SQL中使用存储过程的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/springsnow/p/9394789.html

查看更多关于Oracle在PL/SQL中使用存储过程的详细内容...

  阅读:43次